Skip to content

Commit

Permalink
Version 10.1 with updates to the CreatiVision emulation and improved …
Browse files Browse the repository at this point in the history
…ADAM memory initialization.
  • Loading branch information
wavemotion-dave committed Sep 3, 2024
1 parent 4f8214f commit b82b53c
Show file tree
Hide file tree
Showing 14 changed files with 235 additions and 94 deletions.
Binary file modified ColecoDS.nds
Binary file not shown.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ include $(DEVKITARM)/ds_rules

export TARGET := ColecoDS
export TOPDIR := $(CURDIR)
export VERSION := 10.0b
export VERSION := 10.1

ICON := -b $(CURDIR)/logo.bmp "ColecoDS $(VERSION);wavemotion-dave;/~https://github.com/wavemotion-dave/ColecoDS"

Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,11 @@ And then move the soundbank.h file to the arm9/sources directory

Versions :
-----------------------
V10.1: 03-Sep-2024 by wavemotion-dave
* Fix for the ADC decimal-mode instruction in the 6502 core for the CreatiVision. This fixes a number of problems including hex-digits showing on scores for some games.
* Tweaks and optimizations for the CreatiVision driver. Added most of the common/stable 'undocumented' opcodes.
* Improved emulation accuracy for the ADAM with memory now initialized to alternating 0x00 (even bytes) and 0xFF (odd bytes) per AdamEM and experiments from Shawn Merrick.

V10.0: 10-Aug-2024 by wavemotion-dave
* Adam Sound Enhancer module support to allow AY sound games to play (mostly MSX ports to the ADAM)
* Ignore files that start with a '.' or '_' (mostly to help filter out clear non-game files).
Expand Down
Binary file modified arm9/gfx_data/pdev_bg0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions arm9/source/colecoDS.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ void dsInstallSoundEmuFIFO(void)
//*****************************************************************************
static u8 last_sgm_mode = false;
static u8 last_pencil_mode = false;
static u8 last_creativision_mode = false;
static u8 last_einstein_mode = false;
static u8 last_ay_mode = false;
static u8 last_mc_mode = 0;
Expand All @@ -624,6 +625,7 @@ void ResetStatusFlags(void)
last_ay_mode = false;
last_mc_mode = 0;
last_pencil_mode = 0;
last_creativision_mode = 0;
last_sg1000_mode = 0;
last_pv2000_mode = 0;
last_sordm5_mode = 0;
Expand Down Expand Up @@ -1172,9 +1174,9 @@ void DisplayStatusLine(bool bForce)
}
else if (creativision_mode)
{
if ((creativision_mode != last_pencil_mode) || bForce)
if ((creativision_mode != last_creativision_mode) || bForce)
{
last_pencil_mode = creativision_mode;
last_creativision_mode = creativision_mode;
DSPrint(20,0,6, "CREATIVISION");
last_pal_mode = 99;
}
Expand Down
59 changes: 38 additions & 21 deletions arm9/source/colecomngt.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ u8 adam_ext_ram_used = 0;
u8 sg1000_double_reset = false;

// -----------------------------------------------------------------------
// Used by various systems such as the ADAM and MSX to point to
// Used by various systems such as the ADAM and MSX to point to
// different 8K segments of memory as RAM and Carts are swapped in/out.
// -----------------------------------------------------------------------
u8 *MemoryMap[8] __attribute__((section(".dtcm"))) = {0,0,0,0,0,0,0,0};
Expand Down Expand Up @@ -111,7 +111,7 @@ AY38910 myAY __attribute__((section(".dtcm")));
// ------------------------------------------------------------------------
void coleco_adam_port_setup(void)
{
if (adam_mode) // ADAM mode requires special handling of Port60
if (adam_mode) // ADAM mode requires special handling of Port60
{
Port53 = 0x00; // Init the SGM Port 53
Port60 = (adam_mode == 3) ? 0x0F:0x00; // Adam/Memory Port 60 is in 'ADAM Mode' (unless mode==3 in which case we are loading a .rom while retaining ADAM emulation)
Expand All @@ -124,7 +124,7 @@ void coleco_adam_port_setup(void)
Port60 = 0x0F; // Adam/Memory Port 60 is in 'Colecovision Mode'
Port20 = 0x00; // Adam Net Port 20 not used for CV/SGM mode
Port42 = 0x00; // Not used for CV/SGM mode

if (bSuperGameCart) Port53 = 0x01; // Super Game Carts expect the SGM memory mapped in
}
}
Expand Down Expand Up @@ -184,17 +184,34 @@ void colecoWipeRAM(void)
}
else if (adam_mode)
{
// ----------------------------------------------------------------------------------- ------------
// ADAM has special handling for memory clear. Rather than a 0x00 for clearing memory, we use
// 0x10 which is a pattern that has been shown to work with 'picky' software like Adam Bomb 2.
// ----------------------------------------------------------------------------------- ------------
for (int i=0; i< 0x10000; i++) {RAM_Memory[i] = myConfig.memWipe ? 0x10: (rand() & 0xFF);}

// ----------------------------------------------------------------------------------------------
// ADAM has special handling for memory clear. Thanks to Shawn Merrick who ran some experiments,
// it appears the bulk (but not all) of memory is alternating 0x00 (even) and 0xFF (odd) pattern.
// We replicate that here - it's good enough to run "picky" games like Adam Bomb 2. This is also
// the pattern that AdamEM uses so it's likely very reasonable to use.
// ----------------------------------------------------------------------------------------------
if (myConfig.memWipe)
{
// Alternating 0x00 and 0xFF bytes throughout memory...
for (int i=0; i< 0x10000; i+=2)
{
RAM_Memory[i] = 0x00; RAM_Memory[i+1]=0xFF;
}
}
else
{
// Randomize all bytes...
for (int i=0; i< 0x10000; i++)
{
RAM_Memory[i] = rand() & 0xFF;
}
}

// The Expanded MEM is always cleared to zeros (helps with compression on save/load state)
memset(EXP_Memory, 0x00, 0x10000);
memset(EXP_Memory, 0x00, 0x10000);
if (DSI_RAM_Buffer) memset(DSI_RAM_Buffer, 0x00, (2*1024*1024));
RAM_Memory[0x38] = RAM_Memory[0x66] = 0xC9; // Per AdamEM - put a return at the interrupt locations to solve problems with badly behaving 3rd party software

RAM_Memory[0x38] = RAM_Memory[0x66] = 0xC9; // Per AdamEM - put a return at the interrupt locations to solve problems with badly behaving 3rd party software
}
else if (einstein_mode)
{
Expand Down Expand Up @@ -374,10 +391,10 @@ u8 colecoInit(char *szGame)
disk_unsaved_data[BAY_DISK2] = 0; // No unsaved DISK data to start
disk_unsaved_data[BAY_TAPE] = 0; // No unsaved TAPE data to start
adamnet_init(); // Initialize the Adam Net and disk drives
// Clear existing drives of any disks/tapes and load the new game up

// Clear existing drives of any disks/tapes and load the new game up
for(u8 J=0;J<MAX_DRIVES;++J) adam_drive_eject(J);

// Load the game into memory
RetFct = loadrom(szGame,RAM_Memory);

Expand Down Expand Up @@ -550,7 +567,7 @@ u8 loadrom(const char *filename, u8 * ptr)
u8 bOK = 0;

DSPrint(0,0,6, "LOADING...");

FILE* handle = fopen(filename, "rb");
if (handle != NULL)
{
Expand Down Expand Up @@ -592,7 +609,7 @@ u8 loadrom(const char *filename, u8 * ptr)
mapperMask = 0x00; // No MSX mapper mask
bActivisionPCB = 0; // No Activision PCB
bSuperGameCart = 0; // No Super Game Cart (aka MegaCart2)

// The SordM5 has one game that needs patching to run...
if (sordm5_mode)
{
Expand Down Expand Up @@ -629,11 +646,11 @@ u8 loadrom(const char *filename, u8 * ptr)
strcpy(disk_last_file[BAY_DISK1], ""); // Nothing loaded in the DISK drive yet
strcpy(disk_last_file[BAY_DISK2], ""); // Nothing loaded in the DISK drive yet
strcpy(disk_last_file[BAY_TAPE], ""); // Nothing loaded in the TAPE drive yet

strcpy(disk_last_path[BAY_DISK1], ""); // Nothing loaded in the DISK drive yet
strcpy(disk_last_path[BAY_DISK2], ""); // Nothing loaded in the DISK drive yet
strcpy(disk_last_path[BAY_TAPE], ""); // Nothing loaded in the TAPE drive yet

disk_last_size[BAY_DISK1] = 0; // Nothing loaded in the DISK drive yet
disk_last_size[BAY_DISK2] = 0; // Nothing loaded in the DISK drive yet
disk_last_size[BAY_TAPE] = 0; // Nothing loaded in the TAPE drive yet
Expand Down Expand Up @@ -730,7 +747,7 @@ u8 loadrom(const char *filename, u8 * ptr)
romBankMask = 0x03;
}
else if (myConfig.cvMode == CV_MODE_SUPERCART) // These are the Super Game Cart types... of varying EE sizes
{
{
bSuperGameCart = 1;
SuperGameCartSetup(romSize);
memcpy(ptr, ROM_Memory, 0x2000);
Expand Down Expand Up @@ -1148,7 +1165,7 @@ ITCM_CODE u32 LoopZ80()
// Execute 1 scanline worth of CPU instructions
u32 cycles_to_process = tms_cpu_line + CPU.CycleDeficit;
CPU.CycleDeficit = ExecZ80(cycles_to_process);

// Refresh VDP
if(Loop9918())
{
Expand Down
123 changes: 100 additions & 23 deletions arm9/source/cpu/m6502/Codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,50 +180,127 @@ case 0xD6: MM_Zx(M_DEC);break; /* DEC $ss,x ZP,x */
case 0xF5: MR_Zx(I);M_SBC(I);break; /* SBC $ss,x ZP,x */
case 0xF6: MM_Zx(M_INC);break; /* INC $ss,x ZP,x */

case 0x19: MR_Ay(I);M_ORA(I);break; /* ORA $ssss,y ABS,y */
case 0x1D: MR_Ax(I);M_ORA(I);break; /* ORA $ssss,x ABS,x */
case 0x19: MR_AyP(I);M_ORA(I);break; /* ORA $ssss,y ABS,y */
case 0x1D: MR_AxP(I);M_ORA(I);break; /* ORA $ssss,x ABS,x */
case 0x1E: MM_Ax(M_ASL);break; /* ASL $ssss,x ABS,x */
case 0x39: MR_Ay(I);M_AND(I);break; /* AND $ssss,y ABS,y */
case 0x3D: MR_Ax(I);M_AND(I);break; /* AND $ssss,x ABS,x */
case 0x39: MR_AyP(I);M_AND(I);break; /* AND $ssss,y ABS,y */
case 0x3D: MR_AxP(I);M_AND(I);break; /* AND $ssss,x ABS,x */
case 0x3E: MM_Ax(M_ROL);break; /* ROL $ssss,x ABS,x */
case 0x59: MR_Ay(I);M_EOR(I);break; /* EOR $ssss,y ABS,y */
case 0x5D: MR_Ax(I);M_EOR(I);break; /* EOR $ssss,x ABS,x */
case 0x59: MR_AyP(I);M_EOR(I);break; /* EOR $ssss,y ABS,y */
case 0x5D: MR_AxP(I);M_EOR(I);break; /* EOR $ssss,x ABS,x */
case 0x5E: MM_Ax(M_LSR);break; /* LSR $ssss,x ABS,x */
case 0x79: MR_Ay(I);M_ADC(I);break; /* ADC $ssss,y ABS,y */
case 0x7D: MR_Ax(I);M_ADC(I);break; /* ADC $ssss,x ABS,x */
case 0x79: MR_AyP(I);M_ADC(I);break; /* ADC $ssss,y ABS,y */
case 0x7D: MR_AxP(I);M_ADC(I);break; /* ADC $ssss,x ABS,x */
case 0x7E: MM_Ax(M_ROR);break; /* ROR $ssss,x ABS,x */
case 0x99: MW_Ay(R->A);break; /* STA $ssss,y ABS,y */
case 0x9D: MW_Ax(R->A);break; /* STA $ssss,x ABS,x */
case 0xB9: MR_Ay(R->A);M_FL(R->A);break; /* LDA $ssss,y ABS,y */
case 0xBC: MR_Ax(R->Y);M_FL(R->Y);break; /* LDY $ssss,x ABS,x */
case 0xBD: MR_Ax(R->A);M_FL(R->A);break; /* LDA $ssss,x ABS,x */
case 0xBE: MR_Ay(R->X);M_FL(R->X);break; /* LDX $ssss,y ABS,y */
case 0xD9: MR_Ay(I);M_CMP(R->A,I);break; /* CMP $ssss,y ABS,y */
case 0xDD: MR_Ax(I);M_CMP(R->A,I);break; /* CMP $ssss,x ABS,x */
case 0xB9: MR_AyP(R->A);M_FL(R->A);break; /* LDA $ssss,y ABS,y */
case 0xBC: MR_AxP(R->Y);M_FL(R->Y);break; /* LDY $ssss,x ABS,x */
case 0xBD: MR_AxP(R->A);M_FL(R->A);break; /* LDA $ssss,x ABS,x */
case 0xBE: MR_AyP(R->X);M_FL(R->X);break; /* LDX $ssss,y ABS,y */
case 0xD9: MR_AyP(I);M_CMP(R->A,I);break; /* CMP $ssss,y ABS,y */
case 0xDD: MR_AxP(I);M_CMP(R->A,I);break; /* CMP $ssss,x ABS,x */
case 0xDE: MM_Ax(M_DEC);break; /* DEC $ssss,x ABS,x */
case 0xF9: MR_Ay(I);M_SBC(I);break; /* SBC $ssss,y ABS,y */
case 0xFD: MR_Ax(I);M_SBC(I);break; /* SBC $ssss,x ABS,x */
case 0xF9: MR_AyP(I);M_SBC(I);break; /* SBC $ssss,y ABS,y */
case 0xFD: MR_AxP(I);M_SBC(I);break; /* SBC $ssss,x ABS,x */
case 0xFE: MM_Ax(M_INC);break; /* INC $ssss,x ABS,x */

case 0x01: MR_Ix(I);M_ORA(I);break; /* ORA ($ss,x) INDEXINDIR */
case 0x11: MR_Iy(I);M_ORA(I);break; /* ORA ($ss),y INDIRINDEX */
case 0x11: MR_IyP(I);M_ORA(I);break; /* ORA ($ss),y INDIRINDEX */
case 0x21: MR_Ix(I);M_AND(I);break; /* AND ($ss,x) INDEXINDIR */
case 0x31: MR_Iy(I);M_AND(I);break; /* AND ($ss),y INDIRINDEX */
case 0x31: MR_IyP(I);M_AND(I);break; /* AND ($ss),y INDIRINDEX */
case 0x41: MR_Ix(I);M_EOR(I);break; /* EOR ($ss,x) INDEXINDIR */
case 0x51: MR_Iy(I);M_EOR(I);break; /* EOR ($ss),y INDIRINDEX */
case 0x51: MR_IyP(I);M_EOR(I);break; /* EOR ($ss),y INDIRINDEX */
case 0x61: MR_Ix(I);M_ADC(I);break; /* ADC ($ss,x) INDEXINDIR */
case 0x71: MR_Iy(I);M_ADC(I);break; /* ADC ($ss),y INDIRINDEX */
case 0x71: MR_IyP(I);M_ADC(I);break; /* ADC ($ss),y INDIRINDEX */
case 0x81: MW_Ix(R->A);break; /* STA ($ss,x) INDEXINDIR */
case 0x91: MW_Iy(R->A);break; /* STA ($ss),y INDIRINDEX */
case 0xA1: MR_Ix(R->A);M_FL(R->A);break; /* LDA ($ss,x) INDEXINDIR */
case 0xB1: MR_Iy(R->A);M_FL(R->A);break; /* LDA ($ss),y INDIRINDEX */
case 0xB1: MR_IyP(R->A);M_FL(R->A);break; /* LDA ($ss),y INDIRINDEX */
case 0xC1: MR_Ix(I);M_CMP(R->A,I);break; /* CMP ($ss,x) INDEXINDIR */
case 0xD1: MR_Iy(I);M_CMP(R->A,I);break; /* CMP ($ss),y INDIRINDEX */
case 0xD1: MR_IyP(I);M_CMP(R->A,I);break; /* CMP ($ss),y INDIRINDEX */
case 0xE1: MR_Ix(I);M_SBC(I);break; /* SBC ($ss,x) INDEXINDIR */
case 0xF1: MR_Iy(I);M_SBC(I);break; /* SBC ($ss),y INDIRINDEX */
case 0xF1: MR_IyP(I);M_SBC(I);break; /* SBC ($ss),y INDIRINDEX */


case 0x0A: M_ASL(R->A);break; /* ASL a ACC */
case 0x2A: M_ROL(R->A);break; /* ROL a ACC */
case 0x4A: M_LSR(R->A);break; /* LSR a ACC */
case 0x6A: M_ROR(R->A);break; /* ROR a ACC */

// -------------------------------------------------------------
// Undocumented "illegal" Opcodes below here... this isn't the
// full set just the more 'likely to encounter' stable ones...
// -------------------------------------------------------------

case 0xA3: MR_Ix(R->A);M_FL(R->A);R->X=R->A;break; /* LAX ($ss,x) INDEXINDIR */
case 0xA7: MR_Zp(R->A);M_FL(R->A);R->X=R->A;break; /* LAX $ss ZP */
case 0xAF: MR_Ab(R->A);M_FL(R->A);R->X=R->A;break; /* LAX $ssss ABS */
case 0xB3: MR_IyP(R->A);M_FL(R->A);R->X=R->A;break; /* LAX ($ss),y INDIRINDEX */
case 0xB7: MR_Zx(R->A);M_FL(R->A);R->X=R->A;break; /* LAX $ss,x ZP,x */
case 0xBF: MR_AxP(R->A);M_FL(R->A);R->X=R->A;break; /* LAX $ssss,x ABS,x */

case 0x83: MW_Ix((R->A & R->X));break; /* SAX ($ss,x) INDEXINDIR */
case 0x87: MW_Zp((R->A & R->X));break; /* SAX $ss ZP */
case 0x8F: MW_Ab((R->A & R->X));break; /* SAX $ssss ABS */
case 0x97: MW_Zx((R->A & R->X));break; /* SAX $ss,x ZP,x */

case 0xC7: MM_Zp(M_DCP);break; /* DCP $ss ZP */
case 0xD7: MM_Zx(M_DCP);break; /* DCP $ss,x ZP,x */
case 0xCF: MM_Ab(M_DCP);break; /* DCP $ssss ABS */
case 0xDF: MM_Ax(M_DCP);break; /* DCP $ssss,x ABS,x */
case 0xDB: MM_Ay(M_DCP);break; /* DCP $ssss,y ABS,y */

case 0xCB: MR_Im(I);M_SBX(I);break; /* SBX (A AND X) - oper -> X */

case 0x2B:
case 0x0B: MR_Im(I);M_AND(I);
R->P=(R->P&~C_FLAG)|(I & 0x80 ? C_FLAG:0);
break; /* ANC #$ss IMM with Carry Flag as bit 7*/

case 0x4B: MR_Im(I);M_AND(I);M_LSR(R->A);break; /* ALR #$ss IMM with Carry Flag as bit 0*/

// These are 1-byte NOPs consuming 2 cycles
case 0x1A:
case 0x3A:
case 0x5A:
case 0x7A:
case 0xDA:
case 0xFA:
break;

// These are 2-byte NOPs consuming 2 cycles
case 0x80:
case 0x82:
case 0x89:
case 0xC2:
case 0xE2:
R->PC.W++;
break;

// These are 2-byte NOPs consuming 3 cycles
case 0x04:
case 0x44:
case 0x64:
R->PC.W++;
break;

// These are 2-byte NOPs consuming 4 cycles
case 0x34:
case 0x54:
case 0x74:
case 0xD4:
R->PC.W++;
break;

// These are 3-byte NOPs consuming 4 cycles
case 0x0C:
case 0x1C:
case 0x3C:
case 0x5C:
case 0x7C:
case 0xDC:
case 0xFC:
R->PC.W++;R->PC.W++;
break;

Loading

0 comments on commit b82b53c

Please sign in to comment.