From f49b0d51005f617aff7bf278e95b515103646499 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Tue, 8 Feb 2022 15:19:11 +0800 Subject: [PATCH] bandai.c: Backport (https://github.com/TASEmulators/fceux/commit/6145fe22ab8f6eebc71c5e84b14ed5d4ea87b302#diff-11a2612d6f7ea9399d3d796f82dde9fb84b449a98f22ed187b24643c63c8e5d8) --- src/boards/368.c | 1 - src/boards/bandai.c | 393 +++++++++++++++++++++++++++++++------------- src/driver.h | 2 +- 3 files changed, 277 insertions(+), 119 deletions(-) diff --git a/src/boards/368.c b/src/boards/368.c index 459efbf..4ae27fe 100644 --- a/src/boards/368.c +++ b/src/boards/368.c @@ -81,7 +81,6 @@ static void M368Power(void) { SetWriteHandler(0x4022, 0x4022, M368WritePRG); SetWriteHandler(0x4120, 0x4120, M368WritePRG); SetWriteHandler(0x4122, 0x4122, M368WriteIRQ); - //SetWriteHandler(0x8000, 0xffff, M368WriteUNROM); } static void M368Reset(void) { diff --git a/src/boards/bandai.c b/src/boards/bandai.c index 375d2b0..99d04a0 100644 --- a/src/boards/bandai.c +++ b/src/boards/bandai.c @@ -65,116 +65,202 @@ static SFORMAT StateRegs[] = #define X24C0X_READ 3 #define X24C0X_WRITE 4 -static uint8 x24c0x_data[256], x24c0x_state; -static uint8 x24c0x_addr, x24c0x_word, x24c0x_latch, x24c0x_bitcount; -static uint8 x24c0x_sda, x24c0x_scl, x24c0x_out, x24c0x_oe; +static uint8 x24c0x_data[512]; -static SFORMAT x24c0xStateRegs[] = +static uint8 x24c01_state; +static uint8 x24c01_addr, x24c01_word, x24c01_latch, x24c01_bitcount; +static uint8 x24c01_sda, x24c01_scl, x24c01_out; + +static uint8 x24c02_state; +static uint8 x24c02_addr, x24c02_word, x24c02_latch, x24c02_bitcount; +static uint8 x24c02_sda, x24c02_scl, x24c02_out; + +static SFORMAT x24c01StateRegs[] = { - { &x24c0x_addr, 1, "ADDR" }, - { &x24c0x_word, 1, "WORD" }, - { &x24c0x_latch, 1, "LATC" }, - { &x24c0x_bitcount, 1, "BITC" }, - { &x24c0x_sda, 1, "SDA" }, - { &x24c0x_scl, 1, "SCL" }, - { &x24c0x_out, 1, "OUT" }, - { &x24c0x_oe, 1, "OE" }, - { &x24c0x_state, 1, "STAT" }, + { &x24c01_addr, 1, "ADDR" }, + { &x24c01_word, 1, "WORD" }, + { &x24c01_latch, 1, "LATC" }, + { &x24c01_bitcount, 1, "BITC" }, + { &x24c01_sda, 1, "SDA" }, + { &x24c01_scl, 1, "SCL" }, + { &x24c01_out, 1, "OUT" }, + { &x24c01_state, 1, "STAT" }, { 0 } }; -static void x24c0x_init() { - x24c0x_addr = x24c0x_word = x24c0x_latch = x24c0x_bitcount = x24c0x_sda = x24c0x_scl = x24c0x_oe = 0; - x24c0x_state = X24C0X_STANDBY; +static SFORMAT x24c02StateRegs[] = +{ + { &x24c02_addr, 1, "ADDR" }, + { &x24c02_word, 1, "WORD" }, + { &x24c02_latch, 1, "LATC" }, + { &x24c02_bitcount, 1, "BITC" }, + { &x24c02_sda, 1, "SDA" }, + { &x24c02_scl, 1, "SCL" }, + { &x24c02_out, 1, "OUT" }, + { &x24c02_state, 1, "STAT" }, + { 0 } +}; + +static void x24c01_init(void) { + x24c01_addr = x24c01_word = x24c01_latch = x24c01_bitcount = x24c01_sda = x24c01_scl = 0; + x24c01_state = X24C0X_STANDBY; } -static void x24c0x_write(uint8 data) { - uint8 sda = (data >> 6) & 1; - uint8 scl = (data >> 5) & 1; - x24c0x_oe = (data >> 7); +static void x24c02_init(void) { + x24c02_addr = x24c02_word = x24c02_latch = x24c02_bitcount = x24c02_sda = x24c02_scl = 0; + x24c02_state = X24C0X_STANDBY; +} - if(x24c0x_scl && scl) { - if(x24c0x_sda && !sda) { /* START */ - x24c0x_state = X24C0X_ADDRESS; - x24c0x_bitcount = 0; - x24c0x_addr = 0; - } else if(!x24c0x_sda && sda) { /* STOP */ - x24c0x_state = X24C0X_STANDBY; +static void x24c01_write(uint8 data) { + uint8 scl = (data >> 5) & 1; + uint8 sda = (data >> 6) & 1; + + if(x24c01_scl && scl) { + if(x24c01_sda && !sda) { /* START */ + x24c01_state = X24C0X_ADDRESS; + x24c01_bitcount = 0; + x24c01_addr = 0; + } else if(!x24c01_sda && sda) { /* STOP */ + x24c01_state = X24C0X_STANDBY; } - } else if(!x24c0x_scl && scl) { /* RISING EDGE */ - switch(x24c0x_state) { + } else if(!x24c01_scl && scl) { /* RISING EDGE */ + switch(x24c01_state) { case X24C0X_ADDRESS: - if(x24c0x_bitcount < 7) { - x24c0x_addr <<= 1; - x24c0x_addr |= sda; + if(x24c01_bitcount < 7) { + x24c01_addr <<= 1; + x24c01_addr |= sda; } else { - if(!x24c02) /* X24C01 mode */ - x24c0x_word = x24c0x_addr; - if(sda) { /* READ COMMAND */ - x24c0x_state = X24C0X_READ; - } else { /* WRITE COMMAND */ - if(x24c02) /* X24C02 mode */ - x24c0x_state = X24C0X_WORD; - else - x24c0x_state = X24C0X_WRITE; - } + x24c01_word = x24c01_addr; + if(sda) /* READ COMMAND */ + x24c01_state = X24C0X_READ; + else /* WRITE COMMAND */ + x24c01_state = X24C0X_WRITE; } - x24c0x_bitcount++; - break; - case X24C0X_WORD: - if(x24c0x_bitcount == 8) { /* ACK */ - x24c0x_word = 0; - x24c0x_out = 0; - } else { /* WORD ADDRESS INPUT */ - x24c0x_word <<= 1; - x24c0x_word |= sda; - if(x24c0x_bitcount == 16) { /* END OF ADDRESS INPUT */ - x24c0x_bitcount = 7; - x24c0x_state = X24C0X_WRITE; - } - } - x24c0x_bitcount++; + x24c01_bitcount++; break; case X24C0X_READ: - if (x24c0x_bitcount == 8) { /* ACK */ - x24c0x_out = 0; - x24c0x_latch = x24c0x_data[x24c0x_word]; - x24c0x_bitcount = 0; - } else { /* REAL OUTPUT */ - x24c0x_out = x24c0x_latch >> 7; - x24c0x_latch <<= 1; - x24c0x_bitcount++; - if(x24c0x_bitcount == 8) { - x24c0x_word++; - x24c0x_word &= 0xff; + if (x24c01_bitcount == 8) { /* ACK */ + x24c01_out = 0; + x24c01_latch = x24c0x_data[x24c01_word]; + x24c01_bitcount = 0; + } else { /* REAL OUTPUT */ + x24c01_out = x24c01_latch >> 7; + x24c01_latch <<= 1; + x24c01_bitcount++; + if(x24c01_bitcount == 8) { + x24c01_word++; + x24c01_word &= 0xff; } } break; case X24C0X_WRITE: - if (x24c0x_bitcount == 8) { /* ACK */ - x24c0x_out = 0; - x24c0x_latch = 0; - x24c0x_bitcount = 0; - } else { /* REAL INPUT */ - x24c0x_latch <<= 1; - x24c0x_latch |= sda; - x24c0x_bitcount++; - if(x24c0x_bitcount == 8) { - x24c0x_data[x24c0x_word] = x24c0x_latch; - x24c0x_word++; - x24c0x_word &= 0xff; + if (x24c01_bitcount == 8) { /* ACK */ + x24c01_out = 0; + x24c01_latch = 0; + x24c01_bitcount = 0; + } else { /* REAL INPUT */ + x24c01_latch <<= 1; + x24c01_latch |= sda; + x24c01_bitcount++; + if(x24c01_bitcount == 8) { + x24c0x_data[x24c01_word] = x24c01_latch; + x24c01_word++; + x24c01_word &= 0xff; } } break; } } - x24c0x_sda = sda; - x24c0x_scl = scl; + x24c01_sda = sda; + x24c01_scl = scl; } -static uint8 x24c0x_read() { - return x24c0x_out << 4; +static void x24c02_write(uint8 data) { + uint8 scl = (data >> 5) & 1; + uint8 sda = (data >> 6) & 1; + + if (x24c02_scl && scl) { + if (x24c02_sda && !sda) { /* START */ + x24c02_state = X24C0X_ADDRESS; + x24c02_bitcount = 0; + x24c02_addr = 0; + } else if (!x24c02_sda && sda) { /* STOP */ + x24c02_state = X24C0X_STANDBY; + } + } else if (!x24c02_scl && scl) { /* RISING EDGE */ + switch (x24c02_state) { + case X24C0X_ADDRESS: + if (x24c02_bitcount < 7) { + x24c02_addr <<= 1; + x24c02_addr |= sda; + } else { + if (sda) /* READ COMMAND */ + x24c02_state = X24C0X_READ; + else /* WRITE COMMAND */ + x24c02_state = X24C0X_WORD; + } + x24c02_bitcount++; + break; + case X24C0X_WORD: + if (x24c02_bitcount == 8) { /* ACK */ + x24c02_word = 0; + x24c02_out = 0; + } else { /* WORD ADDRESS INPUT */ + x24c02_word <<= 1; + x24c02_word |= sda; + if (x24c02_bitcount == 16) { /* END OF ADDRESS INPUT */ + x24c02_bitcount = 7; + x24c02_state = X24C0X_WRITE; + } + } + x24c02_bitcount++; + break; + case X24C0X_READ: + if (x24c02_bitcount == 8) { /* ACK */ + x24c02_out = 0; + x24c02_latch = x24c0x_data[x24c02_word|0x100]; + x24c02_bitcount = 0; + } else { /* REAL OUTPUT */ + x24c02_out = x24c02_latch >> 7; + x24c02_latch <<= 1; + x24c02_bitcount++; + if (x24c02_bitcount == 8) { + x24c02_word++; + x24c02_word &= 0xff; + } + } + break; + case X24C0X_WRITE: + if (x24c02_bitcount == 8) { /* ACK */ + x24c02_out = 0; + x24c02_latch = 0; + x24c02_bitcount = 0; + } else { /* REAL INPUT */ + x24c02_latch <<= 1; + x24c02_latch |= sda; + x24c02_bitcount++; + if (x24c02_bitcount == 8) { + x24c0x_data[x24c02_word|0x100] = x24c02_latch; + x24c02_word++; + x24c02_word &= 0xff; + } + } + break; + } + } + + x24c02_sda = sda; + x24c02_scl = scl; +} + +static void SyncMirror(void) { + switch (reg[9] & 3) { + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } } static void Sync(void) { @@ -189,12 +275,7 @@ static void Sync(void) { setprg16(0x8000, reg[8]); setprg16(0xC000, ~0); } - switch (reg[9] & 3) { - case 0: setmirror(MI_V); break; - case 1: setmirror(MI_H); break; - case 2: setmirror(MI_0); break; - case 3: setmirror(MI_1); break; - } + SyncMirror(); } static DECLFW(BandaiWrite) { @@ -207,12 +288,20 @@ static DECLFW(BandaiWrite) { case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break; case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break; case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break; - case 0x0D: x24c0x_write(V); break; + case 0x0D: + if (x24c02) + x24c02_write(V); + else + x24c01_write(V); + break; } } static DECLFR(BandaiRead) { - return (X.DB & 0xEF) | x24c0x_read(); + if (x24c02) + return (X.DB & 0xEF) | (x24c02_out << 4); + else + return (X.DB & 0xEF) | (x24c01_out << 4); } static void FP_FASTAPASS(1) BandaiIRQHook(int a) { @@ -228,7 +317,10 @@ static void FP_FASTAPASS(1) BandaiIRQHook(int a) { static void BandaiPower(void) { IRQa = 0; - x24c0x_init(); + if (x24c02) + x24c02_init(); + else + x24c01_init(); Sync(); SetReadHandler(0x6000, 0x7FFF, BandaiRead); SetReadHandler(0x8000, 0xFFFF, CartBR); @@ -246,12 +338,12 @@ void Mapper16_Init(CartInfo *info) { MapIRQHook = BandaiIRQHook; info->battery = 1; - info->SaveGame[0] = x24c0x_data; + info->SaveGame[0] = x24c0x_data + 256; info->SaveGameLen[0] = 256; AddExState(x24c0x_data, 256, 0, "DATA"); GameStateRestore = StateRestore; - AddExState(&x24c0xStateRegs, ~0, 0, 0); + AddExState(&x24c02StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); } @@ -267,7 +359,7 @@ void Mapper159_Init(CartInfo *info) { AddExState(x24c0x_data, 128, 0, "DATA"); GameStateRestore = StateRestore; - AddExState(&x24c0xStateRegs, ~0, 0, 0); + AddExState(&x24c01StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); } @@ -323,7 +415,9 @@ static int BarcodeReadPos; static int BarcodeCycleCount; static uint32 BarcodeOut; -int FCEUI_DatachSet(const uint8 *rcode) { +/* #define INTERL2OF5 */ + +int FCEUI_DatachSet(uint8 *rcode) { int prefix_parity_type[10][6] = { { 0, 0, 0, 0, 0, 0 }, { 0, 0, 1, 0, 1, 1 }, { 0, 0, 1, 1, 0, 1 }, { 0, 0, 1, 1, 1, 0 }, { 0, 1, 0, 0, 1, 1 }, { 0, 1, 1, 0, 0, 1 }, { 0, 1, 1, 1, 0, 0 }, { 0, 1, 0, 1, 0, 1 }, @@ -346,6 +440,7 @@ int FCEUI_DatachSet(const uint8 *rcode) { }; uint8 code[13 + 1]; uint32 tmp_p = 0; + uint32 csum = 0; int i, j; int len; @@ -359,15 +454,45 @@ int FCEUI_DatachSet(const uint8 *rcode) { #define BS(x) BarcodeData[tmp_p] = x; tmp_p++ - for (j = 0; j < 32; j++) { + for (j = 0; j < 32; j++) { /* delay before sending a code */ BS(0x00); } +#ifdef INTERL2OF5 + + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 */ + BS(1); BS(0); BS(0); /* 0 cs */ + BS(1); BS(1); BS(0); BS(0); /* 1 */ + +#else /* Left guard bars */ BS(1); BS(0); BS(1); if (len == 13 || len == 12) { - uint32 csum; for (i = 0; i < 6; i++) if (prefix_parity_type[code[0]][i]) { @@ -386,24 +511,25 @@ int FCEUI_DatachSet(const uint8 *rcode) { for (j = 0; j < 7; j++) { BS(data_right[code[i]][j]); } - csum = 0; - for (i = 0; i < 12; i++) csum += code[i] * ((i & 1) ? 3 : 1); - csum = (10 - (csum % 10)) % 10; + /* Calc and write down the control code if not assigned, instead, send code as is + Battle Rush uses modified type of codes with different control code calculation */ + if (len == 12) { + for (i = 0; i < 12; i++) + csum += code[i] * ((i & 1) ? 3 : 1); + csum = (10 - (csum % 10)) % 10; + rcode[12] = csum + 0x30; /* update check code to the input string as well */ + rcode[13] = 0; + code[12] = csum; + } for (j = 0; j < 7; j++) { - BS(data_right[csum][j]); + BS(data_right[code[12]][j]); } } else if (len == 8 || len == 7) { - uint32 csum = 0; - - for (i = 0; i < 7; i++) csum += (i & 1) ? code[i] : (code[i] * 3); - - csum = (10 - (csum % 10)) % 10; - - for (i = 0; i < 4; i++) + for (i = 0; i < 4; i++) { for (j = 0; j < 7; j++) { BS(data_left_odd[code[i]][j]); } - + } /* Center guard bars */ BS(0); BS(1); BS(0); BS(1); BS(0); @@ -412,7 +538,12 @@ int FCEUI_DatachSet(const uint8 *rcode) { for (j = 0; j < 7; j++) { BS(data_right[code[i]][j]); } - + csum = 0; + for (i = 0; i < 7; i++) + csum += (i & 1) ? code[i] : (code[i] * 3); + csum = (10 - (csum % 10)) % 10; + rcode[7] = csum + 0x30; /* update check code to the input string as well */ + rcode[8] = 0; for (j = 0; j < 7; j++) { BS(data_right[csum][j]); } @@ -420,6 +551,7 @@ int FCEUI_DatachSet(const uint8 *rcode) { /* Right guard bars */ BS(1); BS(0); BS(1); +#endif for (j = 0; j < 32; j++) { BS(0x00); @@ -435,6 +567,26 @@ int FCEUI_DatachSet(const uint8 *rcode) { return(1); } +static void BarcodeSync(void) { + setchr8(0); + setprg16(0x8000, (reg[8] & 0x0F)); + setprg16(0xC000, 0x0F); + SyncMirror(); +} + +static DECLFW(BarcodeWrite) { + A &= 0x0F; + switch (A) { + case 0x00: reg[0] = (V & 8) << 2; x24c01_write(reg[0xD] | reg[0]); break; /* extra EEPROM x24C01 used in Battle Rush mini-cart */ + case 0x08: + case 0x09: reg[A] = V; BarcodeSync(); break; + case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break; + case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break; + case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break; + case 0x0D: reg[0xD] = V & (~0x20); x24c01_write(reg[0xD] | reg[0]); x24c02_write(V); break; + } +} + static void FP_FASTAPASS(1) BarcodeIRQHook(int a) { BandaiIRQHook(a); @@ -452,7 +604,7 @@ static void FP_FASTAPASS(1) BarcodeIRQHook(int a) { } static DECLFR(BarcodeRead) { - return BarcodeOut; + return (X.DB & 0xE7) | ((x24c02_out | x24c01_out) << 4) | BarcodeOut; } static void M157Power(void) { @@ -462,20 +614,27 @@ static void M157Power(void) { BarcodeOut = 0; BarcodeCycleCount = 0; - Sync(); + x24c01_init(); + x24c02_init(); + BarcodeSync(); - SetWriteHandler(0x6000, 0xFFFF, BandaiWrite); SetReadHandler(0x6000, 0x7FFF, BarcodeRead); SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BarcodeWrite); } void Mapper157_Init(CartInfo *info) { - is153 = 1; + x24c02 = 1; info->Power = M157Power; MapIRQHook = BarcodeIRQHook; GameInfo->cspecial = SIS_DATACH; - + info->battery = 1; + info->SaveGame[0] = x24c0x_data; + info->SaveGameLen[0] = 512; GameStateRestore = StateRestore; + AddExState(x24c0x_data, 512, 0, "DATA"); + AddExState(&x24c01StateRegs, ~0, 0, 0); + AddExState(&x24c02StateRegs, ~0, 0, 0); AddExState(&StateRegs, ~0, 0, 0); } diff --git a/src/driver.h b/src/driver.h index 7e63d29..9529bc4 100644 --- a/src/driver.h +++ b/src/driver.h @@ -235,7 +235,7 @@ int FCEUI_FDSInsert(int oride); int FCEUI_FDSEject(void); void FCEUI_FDSSelect(void); -int FCEUI_DatachSet(const uint8 *rcode); +int FCEUI_DatachSet(uint8 *rcode); #ifdef __cplusplus }