diff --git a/src/boards/516.c b/src/boards/516.c new file mode 100644 index 0000000..ad783a0 --- /dev/null +++ b/src/boards/516.c @@ -0,0 +1,58 @@ +/* FCEUmm - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2020 negativeExponent + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/* NES 2.0 Mapper 516 - Brilliant Com Cocoma Pack */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M516CW(uint32 A, uint8 V) { +/* FCEU_printf("CHR: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + setchr1(A, (V & 0x7F) | ((EXPREGS[0] << 5) & 0x180)); +} + +static void M516PW(uint32 A, uint8 V) { +/* FCEU_printf("PRG: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + setprg8(A, (V & 0x0F) | ((EXPREGS[0] << 4) & 0x30)); +} + +static DECLFW(M516Write) { +/* FCEU_printf("Wr: A:%04x V:%02x R0:%02x\n", A, V, EXPREGS[0]); */ + if (A & 0x10) { + EXPREGS[0] = A & 0xF; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + MMC3_CMDWrite(A, V); +} + +static void M516Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, M516Write); +} + +void Mapper516_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + cwrap = M516CW; + pwrap = M516PW; + info->Power = M516Power; + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c index 48752c0..669399d 100644 --- a/src/boards/mmc1.c +++ b/src/boards/mmc1.c @@ -36,11 +36,21 @@ static uint32 NONSaveRAMSIZE = 0; static void (*MMC1CHRHook4)(uint32 A, uint8 V); static void (*MMC1PRGHook16)(uint32 A, uint8 V); +/* Used to override default wram behavior */ +/* NULL uses default MMC1 wram. Set after GenMMC1Init() is called to override */ +static void (*MMC1WRAMHook8)(void); static uint8 *WRAM = NULL; static uint8 *CHRRAM = NULL; static int is155, is171; +static uint32 MMC1GetCHRBank (uint32 bank) { + if (DRegs[0] & 0x10) /* 4 KiB mode */ + return (DRegs[1 + bank]); + else /* 8 KiB mode */ + return ((DRegs[1] & ~1) | bank); +} + static uint8 MMC1WRAMEnabled(void) { return !(DRegs[3] & 0x10); } @@ -56,14 +66,26 @@ static DECLFR(MAWRAM) { return(Page[A >> 11][A]); } -static void MMC1CHR(void) { +static void MMC1WRAM(void) { if (WRAMSIZE > 8192) { if (WRAMSIZE > 16384) setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); else setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); } +} +static void MMC1CHR(void) { + if (MMC1WRAMHook8) /* Use custom wram hook, currently used for M543 */ + MMC1WRAMHook8(); + else { /* Use default MMC1 wram behavior */ + if (WRAMSIZE > 8192) { + if (WRAMSIZE > 16384) + setprg8r(0x10, 0x6000, (DRegs[1] >> 2) & 3); + else + setprg8r(0x10, 0x6000, (DRegs[1] >> 3) & 1); + } + } if (MMC1CHRHook4) { if (DRegs[0] & 0x10) { MMC1CHRHook4(0x0000, DRegs[1]); @@ -313,7 +335,7 @@ static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int saveram) is155 = 0; info->Close = GenMMC1Close; - MMC1PRGHook16 = MMC1CHRHook4 = 0; + MMC1PRGHook16 = MMC1CHRHook4 = MMC1WRAMHook8 = 0; WRAMSIZE = wram * 1024; NONSaveRAMSIZE = (wram - saveram) * 1024; PRGmask16[0] &= (prg >> 14) - 1; @@ -555,3 +577,127 @@ void Mapper297_Init(CartInfo *info) { AddExState(&latch, 1, 0, "LATC"); AddExState(&mode, 1, 0, "MODE"); } + +/* ---------------------------- Mapper 543 -------------------------------- */ + +/* NES 2.0 Mapper 543 - 1996 無敵智カ卡 5-in-1 (CH-501) */ + +static uint8_t outerBank; +static uint8_t bits; +static uint8_t shift; + +static void M543PRG16(uint32 A, uint8 V) { + setprg16(A, (V & 0x0F) | (outerBank << 4)); +} + +static void M543CHR4(uint32 A, uint8 V) { + setchr4(A, (V & 7)); +} + +static void M543WRAM8(void) { + uint32 wramBank; + if (outerBank & 2) + wramBank = 4 | ((outerBank >> 1) & 2) | (outerBank & 1) ; + else + wramBank = ((outerBank << 1) & 2) | ((MMC1GetCHRBank(0) >> 3) & 1); + setprg8r(0x10, 0x6000, wramBank); +} + +static DECLFW(M543Write) { + bits |= ((V >> 3) & 1) << shift++; + if (shift == 4) { + outerBank = bits; + bits = shift = 0; + MMC1PRG(); + MMC1CHR(); + } +} + +static void M543Reset(void) { + bits = 0; + shift = 0; + outerBank = 0; + MMC1CMReset(); +} + +static void M543Power(void) { + bits = 0; + shift = 0; + outerBank = 0; + GenMMC1Power(); + SetWriteHandler(0x5000, 0x5FFF, M543Write); +} + +void Mapper543_Init(CartInfo *info) { + /* M543 has 32K CHR RAM but only uses 8K, so its safe to set this chr to 0 */ + GenMMC1Init(info, 2048, 32, 64, info->battery ? 64 : 0); + info->Power = M543Power; + info->Reset = M543Reset; + MMC1CHRHook4 = M543CHR4; + MMC1PRGHook16 = M543PRG16; + MMC1WRAMHook8 = M543WRAM8; + AddExState(&bits, 1, 0, "BITS"); + AddExState(&shift, 1, 0, "SHFT"); + AddExState(&outerBank, 1, 0, "BANK"); +} + +/* ---------------------------- Mapper 550 -------------------------------- */ + +/* NES 2.0 Mapper 550 - 7-in-1 1993 Chess Series (JY-015) */ + +static uint8_t latch; +static uint8_t outerBank; + +static void M550PRG16(uint32 A, uint8 V) { + if ((outerBank & 6) == 6) + setprg16(A, (V & 7) | (outerBank << 2)); + else + setprg32(0x8000, (latch >> 4) | (outerBank << 1)); +} + +static void M550CHR4(uint32 A, uint8 V) { + if ((outerBank & 6) == 6) + setchr4(A, (V & 7) | ((outerBank << 2) & 0x18)); + else + setchr8((latch & 3) | ((outerBank << 1) & 0x0C)); +} + +static DECLFW(M550Write7) { + if (!(outerBank & 8)) { + outerBank = A & 15; + MMC1PRG(); + MMC1CHR(); + } +} + +static DECLFW(M550Write8) { + latch = V; + if ((outerBank & 6) == 6) + MMC1_write(A, V); + MMC1PRG(); + MMC1CHR(); +} + +static void M550Reset(void) { + latch = 0; + outerBank = 0; + MMC1CMReset(); +} + +static void M550Power(void) { + latch = 0; + outerBank = 0; + GenMMC1Power(); + SetWriteHandler(0x7000, 0x7FFF, M550Write7); + SetWriteHandler(0x8000, 0xFFFF, M550Write8); +} + +void Mapper550_Init(CartInfo *info) { + GenMMC1Init(info, 512, 128, 8, 0); + info->Power = M550Power; + info->Reset = M550Reset; + MMC1CHRHook4 = M550CHR4; + MMC1PRGHook16 = M550PRG16; + AddExState(&latch, 1, 0, "LATC"); + AddExState(&outerBank, 1, 0, "BANK"); +} diff --git a/src/ines.c b/src/ines.c index 0ae0367..124e9ad 100644 --- a/src/ines.c +++ b/src/ines.c @@ -676,7 +676,9 @@ static BMAPPINGLocal bmap[] = { {(uint8_t*)"830928C", 382, Mapper382_Init}, {(uint8_t*)"NJ064", 534, Mapper534_Init}, {(uint8_t*)"Kid Ikarus (FDS)", 539, Mapper539_Init}, -/* {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, */ + {(uint8_t*)"5-in-1 (CH-501)", 543, Mapper543_Init}, + {(uint8_t*)"", 550, Mapper550_Init}, + {(uint8_t*)"Brilliant Com Cocoma Pack", 516, Mapper516_Init}, /* UNIF to NES 2.0 BOARDS */ @@ -1042,6 +1044,7 @@ static int iNES_Init(int num) { SetupCartCHRMapping(0, VROM, CHRRAMSize, 1); AddExState(VROM, CHRRAMSize, 0, "CHRR"); } + FCEU_printf(" CHR-RAM: %3d KiB\n", CHRRAMSize / 1024); } if (head.ROM_type & 8) AddExState(ExtraNTARAM, 2048, 0, "EXNR"); diff --git a/src/ines.h b/src/ines.h index 1a498d9..d04e641 100644 --- a/src/ines.h +++ b/src/ines.h @@ -253,11 +253,13 @@ void Mapper374_Init(CartInfo *); void Mapper382_Init(CartInfo *); void Mapper381_Init(CartInfo *); void Mapper390_Init(CartInfo *); +void Mapper516_Init(CartInfo *); void Mapper533_Init(CartInfo *); void Mapper534_Init(CartInfo *); void Mapper538_Init(CartInfo *); void Mapper539_Init(CartInfo *); void Mapper541_Init(CartInfo *); void Mapper543_Init(CartInfo *); +void Mapper550_Init(CartInfo *); #endif