Skip to content

Commit

Permalink
Version 2.0 - see readme.md file for details!
Browse files Browse the repository at this point in the history
  • Loading branch information
wavemotion-dave committed Mar 1, 2024
1 parent c04a249 commit 2fbeef8
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 33 deletions.
Binary file modified DS994a.nds
Binary file not shown.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ Be sure to use the START button to save out your configuration options so they p

Emulated Disk Drives :
-----------------------
DS994a will support 3 Disk Drives all at up to 360KB as DSK1, DSK2 and DSK3. The first two drives are fully buffered and read/write. DSK3 is read-only. I'm using the TI99 standard Disk Controller but with a modification to allow up to 360KB drives to be supported. Any writes to disk should be auto-persisted and writen back to the SD card. Please be aware that I've seen the rare glitch when writing to some SD cards - emulation coupled with homebrew libraries for writing the SD on the DS is not perfect. With that in mind, I've added some safeguards... before the write takes place, I rename the original .DSK to .DSK.BAK so it's hanging around. If the write fails and freezes up, the next time you boot the emulator and load that disk, it will check if the .DSK.BAK file is around and will revert to that as needed (it does mean that you will have lost your last save...). Also, in the DISK MENU you can 'BACKUP DISK' which you should do occasionally... this will make a /BAK directory and copy the desired .DSK file into that directory for safe-keeping. Using these precautionary methods, you should be able to work around any potential glitches when writing the disk files back to the SD card. Most users will not run into such issues.
DS994a will support 3 Disk Drives all at up to 360KB as DSK1, DSK2 and DSK3. On the DSi, all three disks are fully buffered read/write. On the older DS-Lite/Phat, only the first two drives are fully buffered and read/write. DSK3 is read-only. I'm using the TI99 standard Disk Controller but with a modification to allow up to 360KB drives to be supported. Any writes to disk should be auto-persisted and writen back to the SD card. Please be aware that I've seen the rare glitch when writing to some SD cards - emulation coupled with homebrew libraries for writing the SD on the DS is not perfect. With that in mind, I've added some safeguards... before the write takes place, I rename the original .DSK to .DSK.BAK so it's hanging around. If the write fails and freezes up, the next time you boot the emulator and load that disk, it will check if the .DSK.BAK file is around and will revert to that as needed (it does mean that you will have lost your last save...). Also, in the DISK MENU you can 'BACKUP DISK' which you should do occasionally... this will make a /BAK directory and copy the desired .DSK file into that directory for safe-keeping. Using these precautionary methods, you should be able to work around any potential glitches when writing the disk files back to the SD card. Most users will not run into such issues.

Keyboards and Menus :
-----------------------
Expand Down Expand Up @@ -243,10 +243,12 @@ And then move the soundbank.h file to the arm9/sources directory

Versions :
-----------------------
V2.0: SOON! by wavemotion-dave
V2.0: 01-Mar-2024 by wavemotion-dave
* Support for .rpk (Rom PacKs - same as used by MAME/MESS).
* Fix for save/load state of games that use RAM (MBX carts, MiniMem, etc)
* Improved SAMS handling so that the proper amount of RAM is detected
* On DSi and above, DSK3 is now fully buffered and writable.
* Lots of small tweaks and cleanups across the board as time permitted.
* Refactored and reduced resources so we free up an additional 256K of valuable memory for the future!

V1.9: 24-Feb-2024 by wavemotion-dave
Expand Down
Binary file modified arm9/gfx_data/ti99kbd.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 8 additions & 6 deletions arm9/source/DS99.c
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,8 @@ void __attribute__ ((noinline)) DisplayStatusLine(bool bForce)
Disk[drive].driveWriteCounter--;
if (Disk[drive].driveWriteCounter)
{
DS_Print(11,0,6, "DISK WRITE");
sprintf(tmpBuf, "DISK %d WRITE", drive+1);
DS_Print(11,0,6, tmpBuf);
if (globalConfig.floppySound)
{
if (++floppy_sfx_dampen & 1) mmEffect(SFX_FLOPPY);
Expand All @@ -453,7 +454,7 @@ void __attribute__ ((noinline)) DisplayStatusLine(bool bForce)
{
// Persist the disk - write it back to the SD card
disk_write_to_sd(drive);
DS_Print(11,0,6, " ");
DS_Print(11,0,6, " ");
floppy_sfx_dampen = 0;
}
}
Expand All @@ -462,15 +463,16 @@ void __attribute__ ((noinline)) DisplayStatusLine(bool bForce)
Disk[drive].driveReadCounter--;
if (Disk[drive].driveReadCounter)
{
DS_Print(11,0,6, "DISK READ ");
sprintf(tmpBuf, "DISK %d READ ", drive+1);
DS_Print(11,0,6, tmpBuf);
if (globalConfig.floppySound)
{
if (++floppy_sfx_dampen & 1) mmEffect(SFX_FLOPPY);
}
}
else
{
DS_Print(11,0,6, " ");
DS_Print(11,0,6, " ");
floppy_sfx_dampen = 0;
}
}
Expand Down Expand Up @@ -1770,9 +1772,9 @@ int main(int argc, char **argv)
}
else
{
DS_Print(2,10,0,"ERROR: TI99 BIOS NOT FOUND");
DS_Print(2,10,0,"ERROR: TI994a BIOS NOT FOUND");
DS_Print(2,12,0,"ERROR: CANT RUN WITHOUT BIOS");
DS_Print(3,12,0,"ERROR: SEE README FILE");
DS_Print(3,12,0,"ERROR: SEE README.MD FILE");
while(1) ; // We're done... Need a TI99 bios to run this emulator
}

Expand Down
4 changes: 2 additions & 2 deletions arm9/source/cpu/tms9900/tms9900.c
Original file line number Diff line number Diff line change
Expand Up @@ -1280,9 +1280,9 @@ static inline __attribute__((always_inline)) void TsTd_Accurate(void)
void TMS9900_ContextSwitch(u16 address)
{
// Do it the Classic99 way...
u16 x1 = tms9900.WP; // Save old WP
u16 old_wp = tms9900.WP; // Save old WP
tms9900.WP = MemoryRead16(address+0); // Set the new Workspace
MemoryWrite16(WP_REG(13), x1); // Set the old Workspace Pointer
MemoryWrite16(WP_REG(13), old_wp); // Set the old Workspace Pointer
MemoryWrite16(WP_REG(14), tms9900.PC); // Set the old PC
MemoryWrite16(WP_REG(15), tms9900.ST); // Set the old Status
tms9900.PC = MemoryRead16(address+2); // Set the new PC based on original workspace
Expand Down
2 changes: 0 additions & 2 deletions arm9/source/cpu/tms9918a/tms9918a.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ u8 IH __attribute__((section(".dtcm"))) = 0;
u8 scan_collisions_every __attribute__((section(".dtcm"))) = 32;
u8 CollisionCheckEvery[] = {255, 4, 8, 16, 32, 64, 255};

extern u32 debug[];

// ---------------------------------------------------------------------------------------
// Screen handlers and masks for VDP table address registers.
// Screen modes are confusing as different documentation (MSX, Coleco, VDP manuals, etc)
Expand Down
51 changes: 30 additions & 21 deletions arm9/source/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,11 @@ u8 driveSelected = DSK1; // We support DSK1, DSK2 and DSK3
Disk_t Disk[MAX_DSKS]; // Contains all the Disk sector data plus some metadata for DSK1, DSK2 and DSK3
u8 Disk1_ImageBuf[MAX_DSK_SIZE]; // Full buffering of 360K
u8 Disk2_ImageBuf[MAX_DSK_SIZE]; // Full buffering of 360K
u8 Disk3_ImageBuf[512]; // First two sectors only - but as a bonus, DSK3 can hold 400K (max 1600 sectors allowed by TI controller)
u8 Disk3_ImageBuf[512]; // First two sectors only for the DS-Lite/Phat but full buffering on DSi (who will use the SharedMemBuffer[])

char backup_filename[MAX_PATH]; // If the user wants, they can backup either of DSK1 or DSK2 (the writeable disks)

u16 max_sectors[MAX_DSKS] = // For DSK1 and DSK2 we support 1440x256=360K and for DSK3 we allow the full 1600x256=400K
{1440, 1440, 1600};
#define MAX_DSK_SECTORS 1440 // For all disks we support 1440x256=360K

#define ERR_DEVICEERROR 6 // This is the only error we support. Good enough.

Expand All @@ -90,7 +89,16 @@ void disk_init(void)

Disk[DSK1].image = Disk1_ImageBuf; // Buffered
Disk[DSK2].image = Disk2_ImageBuf; // Buffered
Disk[DSK3].image = Disk3_ImageBuf; // Non-Buffered. This one is read-only. We cache the first two sectors only. Saves us 360KB of memory.

if (isDSiMode())
{
extern u8 SharedMemBuffer[];
Disk[DSK3].image = SharedMemBuffer; // For DSi we fully buffer 360K for DSK3. The DSi is otherwise not really using the SharedMemBuffer[]
}
else
{
Disk[DSK3].image = Disk3_ImageBuf; // Non-Buffered. This one is read-only. We cache the first two sectors only. Saves us valuable memory on the older handhelds.
}
}

// ------------------------------------------------------
Expand Down Expand Up @@ -249,8 +257,9 @@ void WriteTICCRegister(u16 address, u8 val)
}

// --------------------------------------------------------------------------
// This is really only used for DSK3 which is not fully buffered in memory
// and so we must go out to the actual .dsk file and seek/read in the sector.
// This is really only used for DSK3 on the older DS-Lite/Phat where the
// disk is not fully buffered in memory and so we must go out to the actual
// .dsk file and seek/read in the sector.
// --------------------------------------------------------------------------
static void ReadSector(u8 drive, u16 sector, u8 *buf)
{
Expand All @@ -260,7 +269,7 @@ void WriteTICCRegister(u16 address, u8 val)
chdir(Disk[drive].path);

// Make sure the sector being asked for is sensible...
if (sector < max_sectors[drive])
if (sector < MAX_DSK_SECTORS)
{
// Seek to the right sector and read in 256 bytes...
FILE *infile = fopen(Disk[drive].filename, "rb");
Expand Down Expand Up @@ -319,7 +328,7 @@ void WriteTICCRegister(u16 address, u8 val)
// --------------------------------------------------
// Make sure the sector asked for is within reason...
// --------------------------------------------------
if (sectorNumber >= max_sectors[drive])
if (sectorNumber >= MAX_DSK_SECTORS)
{
success = false;
}
Expand All @@ -330,12 +339,12 @@ void WriteTICCRegister(u16 address, u8 val)
// -----------------------------------------------------------------
// Move the 256 byte sector from the .DSK image to the VDP memory
// -----------------------------------------------------------------
if (drive == DSK3)
if (!isDSiMode() && (drive == DSK3))
{
// DSK3 is not cached in memory - so read the sector out from the file.
// DSK3 is not cached in memory on older DS-Lite/Phat - so read the sector out from the file.
ReadSector(drive, sectorNumber, &pVDPVidMem[destVDP]);
}
else
else // Fully buffered - just grab from memory
{
memcpy(&pVDPVidMem[destVDP], &Disk[drive].image[index], 256);
}
Expand All @@ -345,7 +354,7 @@ void WriteTICCRegister(u16 address, u8 val)
}
else // Must be write
{
if (drive != DSK3) // We only support write-back on DSK1 and DSK2
if (isDSiMode() || (drive != DSK3)) // We only support write-back on DSK1 and DSK2 for DS-Lite/Phat
{
memcpy(&Disk[drive].image[index], &pVDPVidMem[destVDP],256);
*((u16*)&MemCPU[0x834A]) = sectorNumber; // fill in the return data
Expand Down Expand Up @@ -419,11 +428,11 @@ void disk_unmount(u8 drive)
{
if (Disk[drive].isDirty) disk_write_to_sd(drive);
Disk[drive].isMounted = false;
if (drive != DSK3)
if (isDSiMode() || (drive != DSK3))
{
memset(Disk[drive].image, 0x00, MAX_DSK_SIZE);
}
else
else // For DS-Lite/Phat we only have a 2 sector buffer
{
memset(Disk[drive].image, 0x00, 512);
}
Expand All @@ -437,9 +446,9 @@ ITCM_CODE void disk_read_from_sd(u8 drive)
FILE *infile = fopen(Disk[drive].filename, "rb");
if (infile)
{
if (drive != DSK3)
if (isDSiMode() || (drive != DSK3))
{
fread(Disk[drive].image, 1, MAX_DSK_SIZE, infile); // For DSK1 and DSK2 we buffer it all
fread(Disk[drive].image, 1, MAX_DSK_SIZE, infile); // For DSK1 and DSK2 we buffer it all. DSi can also buffer DSK3
}
else
{
Expand All @@ -451,8 +460,8 @@ ITCM_CODE void disk_read_from_sd(u8 drive)

ITCM_CODE void disk_write_to_sd(u8 drive)
{
// Only DSK1 and DSK2 support write-back
if (drive != DSK3)
// Only DSK1 and DSK2 support write-back on DS-Lite/Phat
if (isDSiMode() || (drive != DSK3))
{
// Change into the last known DSKs directory for this file
chdir(Disk[drive].path);
Expand All @@ -475,8 +484,8 @@ ITCM_CODE void disk_read_from_sd(u8 drive)

void disk_backup_to_sd(u8 drive)
{
// Only DSK1 and DSK2 support backup
if (drive != DSK3)
// Only DSK1 and DSK2 support backup on DS-Lite/Phat
if (isDSiMode() || (drive != DSK3))
{
// Change into the last known DSKs directory for this file
chdir(Disk[drive].path);
Expand Down Expand Up @@ -514,7 +523,7 @@ void disk_get_file_listing(u8 drive)
{
sectorPtr = (Disk[drive].image[256 + (i+0)] << 8) | (Disk[drive].image[256 + (i+1)] << 0);
if (sectorPtr == 0) break;
if (drive == DSK3)
if (!isDSiMode() && (drive == DSK3))
{
ReadSector(drive, sectorPtr, fileBuf);
for (u8 j=0; j<10; j++)
Expand Down

0 comments on commit 2fbeef8

Please sign in to comment.