From 1c2eabf8b2490e4a89a3062674874a09da225510 Mon Sep 17 00:00:00 2001 From: FIX94 Date: Mon, 21 Aug 2017 06:12:09 +0200 Subject: [PATCH] MMC5 support --- README.md | 2 +- main.c | 11 +- mapper.c | 17 +- mapper.h | 6 +- mapper/m5.c | 596 ++++++++++++++++++++++++++++++++++++++++++++++++++ mapperList.c | 513 +++++++++++++++++++++---------------------- mapperList.h | 2 + mapper_h/m5.h | 22 ++ ppu.c | 112 +++++++--- ppu.h | 3 + 10 files changed, 989 insertions(+), 295 deletions(-) create mode 100644 mapper/m5.c create mode 100644 mapper_h/m5.h diff --git a/README.md b/README.md index d398fe2..15f3171 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is yet another NES Emulator which was written so I can learn about the NES, If you want to check it out for some reason I do include a windows binary in the "Releases" tab, if you want to compile it go check out the "build" files. You will need freeglut as well as openal-soft to compile the project, it should run on most systems since it is fairly generic C code. NTSC and PAL .nes ROMs are supported right now, it also creates .sav files if the chosen game supports saving. -Supported Mappers: 0,1,2,3,4,7,9,10,11,13,15,21,22,23,24,25,26,33,34,36,37,38,44,45,46,47,48,52,61,66,70,71,75,78,79,85,87,89,93,94,97,99,101,113,133,140,144,145,146,147,148,149,152,180,184,185,240 and 242. +Supported Mappers: 0,1,2,3,4,5,7,9,10,11,13,15,21,22,23,24,25,26,33,34,36,37,38,44,45,46,47,48,52,61,66,70,71,75,78,79,85,87,89,93,94,97,99,101,113,133,140,144,145,146,147,148,149,152,180,184,185,240 and 242. Normal .nes files are supported, if you are starting a PAL NES title then make sure it has (E) in the name to be started in PAL mode. You can also play FDS titles if you have the FDS BIOS named disksys.rom in the same folder as your .fds/.qd files. You can also listen to .nsf files, changing tracks works by pressing left/right. diff --git a/main.c b/main.c index 3d4b61b..b9f1f89 100644 --- a/main.c +++ b/main.c @@ -32,7 +32,7 @@ #define DEBUG_KEY 0 #define DEBUG_LOAD_INFO 1 -static const char *VERSION_STRING = "fixNES Alpha v0.9.1"; +static const char *VERSION_STRING = "fixNES Alpha v0.9.2"; static char window_title[256]; static char window_title_pause[256]; @@ -124,8 +124,13 @@ int main(int argc, char** argv) bool trainer = (emuNesROM[6] & (1<<2)) != 0; uint32_t prgROMsize = emuNesROM[4] * 0x4000; uint32_t chrROMsize = emuNesROM[5] * 0x2000; - emuPrgRAMsize = emuNesROM[8] * 0x2000; - if(emuPrgRAMsize == 0) emuPrgRAMsize = 0x2000; + if(mapper == 5) //just to be on the safe side + emuPrgRAMsize = 0x10000; + else + { + emuPrgRAMsize = emuNesROM[8] * 0x2000; + if(emuPrgRAMsize == 0) emuPrgRAMsize = 0x2000; + } emuPrgRAM = malloc(emuPrgRAMsize); uint8_t *prgROM = emuNesROM+16; if(trainer) diff --git a/mapper.c b/mapper.c index bb11fcb..5aa4fb8 100644 --- a/mapper.c +++ b/mapper.c @@ -12,13 +12,16 @@ #include "mapperList.h" #include "mapper_h/nsf.h" #include "mapper_h/fds.h" +#include "ppu.h" get8FuncT mapperGet8; set8FuncT mapperSet8; -getChrFuncT mapperGetChr; chrGet8FuncT mapperChrGet8; chrSet8FuncT mapperChrSet8; +vramGet8FuncT mapperVramGet8; +vramSet8FuncT mapperVramSet8; cycleFuncT mapperCycle; +uint8_t mapperChrMode; bool mapperInit(uint8_t mapper, uint8_t *prgROM, uint32_t prgROMsize, uint8_t *prgRAM, uint32_t prgRAMsize, uint8_t *chrROM, uint32_t chrROMsize) { @@ -33,6 +36,16 @@ bool mapperInit(uint8_t mapper, uint8_t *prgROM, uint32_t prgROMsize, uint8_t *p mapperChrGet8 = mapperList[mapper].chrGet8F; mapperChrSet8 = mapperList[mapper].chrSet8F; mapperCycle = mapperList[mapper].cycleFuncF; + //some mappers re-route VRAM + if(mapperList[mapper].vramGet8F == NULL) + mapperVramGet8 = ppuVRAMGet8; + else + mapperVramGet8 = mapperList[mapper].vramGet8F; + if(mapperList[mapper].vramSet8F == NULL) + mapperVramSet8 = ppuVRAMSet8; + else + mapperVramSet8 = mapperList[mapper].vramSet8F; + mapperChrMode = 0; return true; } @@ -44,6 +57,7 @@ bool mapperInitNSF(uint8_t *nsfBIN, uint32_t nsfBINsize, uint8_t *prgRAM, uint32 mapperChrGet8 = nsfchrGet8; mapperChrSet8 = nsfchrSet8; mapperCycle = nsfcycle; + mapperChrMode = 0; return true; } @@ -78,5 +92,6 @@ bool mapperInitFDS(uint8_t *fdsFile, bool fdsSideB, uint8_t *prgRAM, uint32_t pr mapperChrGet8 = fdschrGet8; mapperChrSet8 = fdschrSet8; mapperCycle = fdscycle; + mapperChrMode = 0; return true; } diff --git a/mapper.h b/mapper.h index fcf30f5..adf8adb 100644 --- a/mapper.h +++ b/mapper.h @@ -13,7 +13,8 @@ typedef uint8_t (*get8FuncT)(uint16_t, uint8_t); typedef void (*set8FuncT)(uint16_t, uint8_t); typedef uint8_t (*chrGet8FuncT)(uint16_t); typedef void (*chrSet8FuncT)(uint16_t, uint8_t); -typedef uint8_t* (*getChrFuncT)(); +typedef uint8_t (*vramGet8FuncT)(uint16_t); +typedef void (*vramSet8FuncT)(uint16_t, uint8_t); typedef void (*cycleFuncT)(); bool mapperInit(uint8_t mapper, uint8_t *prgROM, uint32_t prgROMsize, uint8_t *prgRAM, uint32_t prgRAMsize, uint8_t *chrROM, uint32_t chrROMsize); @@ -24,6 +25,9 @@ extern get8FuncT mapperGet8; extern set8FuncT mapperSet8; extern chrGet8FuncT mapperChrGet8; extern chrSet8FuncT mapperChrSet8; +extern vramGet8FuncT mapperVramGet8; +extern vramSet8FuncT mapperVramSet8; extern cycleFuncT mapperCycle; +extern uint8_t mapperChrMode; #endif diff --git a/mapper/m5.c b/mapper/m5.c new file mode 100644 index 0000000..038ee0b --- /dev/null +++ b/mapper/m5.c @@ -0,0 +1,596 @@ +/* + * Copyright (C) 2017 FIX94 + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#include +#include +#include +#include +#include "../ppu.h" +#include "../mapper.h" +#include "../audio_mmc5.h" + +static uint8_t *m5_prgROM; +static uint8_t *m5_prgRAM; +static uint8_t *m5_chrROM; +static uint32_t m5_prgROMsize; +static uint32_t m5_prgRAMsize; +static uint32_t m5_chrROMsize; +static uint8_t m5_chrRAM[0x2000]; +static uint8_t m5_VRAM[0x800]; +static uint8_t m5_exRAM[0x400]; +static uint32_t m5_PRGRAMBank0; +static uint32_t m5_PRGBank[4]; +static uint8_t m5_PRGBankType[3]; +static uint32_t m5_CHRBank[12]; +static uint8_t m5_prg_bank_mode; +static uint8_t m5_chr_bank_mode; +static uint8_t m5_irqCtr; +static uint8_t m5_irqVal; +static uint8_t m5_fillTile; +static uint8_t m5_fillAttr; +static bool m5_irqEnable; +static bool m5_inFrame; +static bool m5_irqPending; +static bool m5_chrSet; +static bool m5_split; +static bool m5_splitRight; +static uint8_t m5_splitTile; +static uint8_t m5_splitBank; +extern bool mapper_interrupt; +static uint16_t m5_prevAddr; +static uint8_t m5_mulA, m5_mulB; +static uint16_t m5_mulRes; +static uint32_t m5_prgROMand; +static uint32_t m5_prgRAMand; +static uint32_t m5_chrROMand; +static uint32_t m5_prgRAMBank0add; +static uint32_t m5_prgRAMadd[4]; +//used externally +uint8_t m5_exMode; + +void m5init(uint8_t *prgROMin, uint32_t prgROMsizeIn, + uint8_t *prgRAMin, uint32_t prgRAMsizeIn, + uint8_t *chrROMin, uint32_t chrROMsizeIn) +{ + m5_prgROM = prgROMin; + m5_prgROMsize = prgROMsizeIn; + m5_prgRAM = prgRAMin; + m5_prgRAMsize = prgRAMsizeIn; + m5_prgROMand = prgROMsizeIn-1; + m5_prgRAMand = prgRAMsizeIn-1; + if(chrROMsizeIn > 0) + { + m5_chrROM = chrROMin; + m5_chrROMsize = chrROMsizeIn; + m5_chrROMand = chrROMsizeIn-1; + } + else + { + m5_chrROM = m5_chrRAM; + m5_chrROMsize = 0x2000; + m5_chrROMand = 0x1FFF; + } + m5_PRGRAMBank0 = 0; + memset(m5_PRGBank,0,3*sizeof(uint32_t)); + m5_PRGBank[3] = 0xFF; + memset(m5_PRGBankType,0,3*sizeof(uint8_t)); + memset(m5_chrRAM,0,0x2000); + memset(m5_VRAM,0,0x800); + memset(m5_exRAM,0,0x400); + memset(m5_CHRBank,0,12*sizeof(uint32_t)); + m5_irqCtr = 0; + m5_irqEnable = false; + m5_inFrame = false; + m5_irqPending = false; + m5_chrSet = false; + m5_split = false; + m5_splitRight = false; + m5_splitTile = 0; + m5_splitBank = 0; + m5_exMode = 0; + m5_irqVal = 0; + m5_fillTile = 0; + m5_fillAttr = 0; + m5_prg_bank_mode = 3; + m5_chr_bank_mode = 3; + m5_prevAddr = 0; + m5_mulA = 0, m5_mulB = 0; + m5_mulRes = 0; + m5_prgRAMBank0add = 0; + memset(m5_prgRAMadd,0,4*sizeof(uint32_t)); + mmc5AudioInit(); + printf("Mapper 5 inited\n"); +} + +extern bool ppuInFrame; +extern bool ppuScanlineDone; +extern bool ppu816Sprite; + +uint8_t m5get8(uint16_t addr, uint8_t val) +{ + if(addr >= 0x5000 && addr < 0x5016) + return mmc5AudioGet8(addr&0x1F); + if(addr >= 0x5200 && addr < 0x5207) + { + //printf("m5get8 %04x\n", addr); + uint8_t val; + switch(addr&7) + { + case 3: + return m5_irqVal; + case 4: + val = (m5_irqPending<<7)|(m5_inFrame<<6); + m5_irqPending = false; + mapper_interrupt = false; + //printf("%08x\n",val); + return val; + case 5: + return m5_mulRes&0xFF; + case 6: + return m5_mulRes>>8; + } + } + else if(addr >= 0x5C00 && addr < 0x6000 && m5_exMode >= 2) + return m5_exRAM[addr&0x3FF]; + else if(addr >= 0x6000 && addr < 0x8000) + return m5_prgRAM[(((m5_PRGRAMBank0<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMBank0add]; + else if(addr >= 0x8000) + { + switch(m5_prg_bank_mode) + { + case 0: + return m5_prgROM[(((m5_PRGBank[3]&~3)<<13)+(addr&0x7FFF))&m5_prgROMand]; + case 1: + if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 1) //ROM + return m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]]; + } + else + return m5_prgROM[(((m5_PRGBank[3]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand]; + case 2: + if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 1) //ROM + return m5_prgROM[(((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]]; + } + else if(addr < 0xE000) + { + if(m5_PRGBankType[2] == 1) //ROM + return m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]]; + } + else + return m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand]; + case 3: + if(addr < 0xA000) + { + if(m5_PRGBankType[0] == 1) //ROM + return m5_prgROM[((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[(((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[0]]; + } + else if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 1) //ROM + return m5_prgROM[((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[(((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[1]]; + } + else if(addr < 0xE000) + { + if(m5_PRGBankType[2] == 1) //ROM + return m5_prgROM[((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgROMand]; + else //RAM + return m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]]; + } + else + return m5_prgROM[((m5_PRGBank[3]<<13)+(addr&0x1FFF))&m5_prgROMand]; + default: + break; + } + } + return val; +} + +extern bool cpuWriteTMP; +void m5set8(uint16_t addr, uint8_t val) +{ + //printf("m5set8 %04x %02x\n", addr, val); + if(addr >= 0x5000 && addr < 0x5016) + mmc5AudioSet8(addr&0x1F, val); + else if(addr >= 0x5100 && addr < 0x512C) + { + //printf("m5set8 %04x %02x\n", addr, val); + uint16_t v1,v2,v3,v4; + switch(addr&0x3F) + { + case 0: + m5_prg_bank_mode = val&3; + break; + case 1: + m5_chr_bank_mode = val&3; + break; + case 4: + m5_exMode = val&3; + break; + case 5: + v1 = (val&3)<<10; + v2 = ((val>>2)&3)<<10; + v3 = ((val>>4)&3)<<10; + v4 = ((val>>6)&3)<<10; + ppuSetNameTblCustom(v1,v2,v3,v4); + break; + case 6: + m5_fillTile = val; + break; + case 7: + m5_fillAttr = val&3; + break; + case 0x13: + m5_PRGRAMBank0 = val&3; + m5_prgRAMBank0add = (val&4)?0x8000:0; + break; + case 0x14: + m5_PRGBankType[0] = (val&0x80)!=0; + if(m5_PRGBankType[0] == 1) //ROM + m5_PRGBank[0] = val&0x7F; + else //RAM + { + m5_PRGBank[0] = val&3; + m5_prgRAMadd[0] = (val&4)?0x8000:0; + } + break; + case 0x15: + m5_PRGBankType[1] = (val&0x80)!=0; + if(m5_PRGBankType[1] == 1) //ROM + m5_PRGBank[1] = val&0x7F; + else //RAM + { + m5_PRGBank[1] = val&3; + m5_prgRAMadd[1] = (val&4)?0x8000:0; + } + break; + case 0x16: + m5_PRGBankType[2] = (val&0x80)!=0; + if(m5_PRGBankType[2] == 1) //ROM + m5_PRGBank[2] = val&0x7F; + else //RAM + { + m5_PRGBank[2] = val&3; + m5_prgRAMadd[2] = (val&4)?0x8000:0; + } + break; + case 0x17: + //always ROM + m5_PRGBank[3] = val&0x7F; + break; + case 0x20: + m5_CHRBank[0] = val; + m5_chrSet = false; + break; + case 0x21: + m5_CHRBank[1] = val; + m5_chrSet = false; + break; + case 0x22: + m5_CHRBank[2] = val; + m5_chrSet = false; + break; + case 0x23: + m5_CHRBank[3] = val; + m5_chrSet = false; + break; + case 0x24: + m5_CHRBank[4] = val; + m5_chrSet = false; + break; + case 0x25: + m5_CHRBank[5] = val; + m5_chrSet = false; + break; + case 0x26: + m5_CHRBank[6] = val; + m5_chrSet = false; + break; + case 0x27: + m5_CHRBank[7] = val; + m5_chrSet = false; + break; + case 0x28: + m5_CHRBank[0x8] = val; + m5_chrSet = true; + break; + case 0x29: + m5_CHRBank[0x9] = val; + m5_chrSet = true; + break; + case 0x2A: + m5_CHRBank[0xA] = val; + m5_chrSet = true; + break; + case 0x2B: + m5_CHRBank[0xB] = val; + m5_chrSet = true; + break; + } + } + else if(addr >= 0x5200 && addr < 0x5207) + { + //printf("m5set8 %04x %02x\n", addr, val); + switch(addr&7) + { + case 0: + m5_split = (val&0x80)!=0; + m5_splitRight = (val&0x40)!=0; + m5_splitTile = val&0x1F; + break; + case 1: + //ignored for now + break; + case 2: + m5_splitBank = val; + break; + case 3: + m5_irqVal = val; + break; + case 4: + m5_irqEnable = (val&0x80)!=0; + break; + case 5: + m5_mulA = val; + m5_mulRes = m5_mulA*m5_mulB; + break; + case 6: + m5_mulB = val; + m5_mulRes = m5_mulA*m5_mulB; + break; + } + } + else if(addr >= 0x5C00 && addr < 0x6000) + m5_exRAM[addr&0x3FF] = val; + else if(addr >= 0x6000 && addr < 0x8000) + m5_prgRAM[(((m5_PRGRAMBank0<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMBank0add] = val; + else if(addr >= 0x8000) + { + switch(m5_prg_bank_mode) + { + case 0: + //ROM Only + break; + case 1: + if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 0) //RAM + m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]] = val; + } + case 2: + if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 0) //RAM + m5_prgRAM[((((m5_PRGBank[1]&~1)<<13)+(addr&0x3FFF))&m5_prgRAMand)|m5_prgRAMadd[1]] = val; + } + else if(addr < 0xE000) + { + if(m5_PRGBankType[2] == 0) //RAM + m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]] = val; + } + case 3: + if(addr < 0xA000) + { + if(m5_PRGBankType[0] == 0) //RAM + m5_prgRAM[(((m5_PRGBank[0]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[0]] = val; + } + else if(addr < 0xC000) + { + if(m5_PRGBankType[1] == 0) //RAM + m5_prgRAM[(((m5_PRGBank[1]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[1]] = val; + } + else if(addr < 0xE000) + { + if(m5_PRGBankType[2] == 0) //RAM + m5_prgRAM[(((m5_PRGBank[2]<<13)+(addr&0x1FFF))&m5_prgRAMand)|m5_prgRAMadd[2]] = val; + } + default: + break; + } + } +} +extern uint8_t ppuDrawnXTile; +uint8_t m5chrGet8(uint16_t addr) +{ + //printf("%04x\n",addr); + if(mapperChrMode == 0) + { + if(m5_split && m5_exMode < 2) + { + if((!m5_splitRight && ppuDrawnXTile < m5_splitTile) || + (m5_splitRight && ppuDrawnXTile >= m5_splitTile)) + return m5_chrROM[(((m5_splitBank<<12)+(addr&0xFFF))&m5_chrROMand)]; + } + else if(m5_exMode == 1) //Special ROM Bank per tile + return m5_chrROM[((((m5_exRAM[ppuGetCurVramAddr()&0x3FF]&0x3F)<<12)+(addr&0xFFF))&m5_chrROMand)]; + } + bool readLowRegs = true; + if(ppu816Sprite) + { + if(mapperChrMode == 0) //BG + readLowRegs = false; + else if(mapperChrMode == 1) //Sprite + readLowRegs = true; + else if(mapperChrMode == 2) //2007 + { + if(m5_chrSet) + readLowRegs = false; + else + readLowRegs = true; + } + } + if(readLowRegs) + { + switch(m5_chr_bank_mode) + { + case 0: //8KB Pages + return m5_chrROM[(((m5_CHRBank[7]<<13)+(addr&0x1FFF))&m5_chrROMand)]; + case 1: //4KB Pages + if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[3]<<12)+(addr&0xFFF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[7]<<12)+(addr&0xFFF))&m5_chrROMand)]; + case 2: //2KB Pages + if(addr < 0x800) + return m5_chrROM[(((m5_CHRBank[1]<<11)+(addr&0x7FF))&m5_chrROMand)]; + if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[3]<<11)+(addr&0x7FF))&m5_chrROMand)]; + if(addr < 0x1800) + return m5_chrROM[(((m5_CHRBank[5]<<11)+(addr&0x7FF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[7]<<11)+(addr&0x7FF))&m5_chrROMand)]; + case 3: //1KB Pages + if(addr < 0x400) + return m5_chrROM[(((m5_CHRBank[0]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x800) + return m5_chrROM[(((m5_CHRBank[1]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0xC00) + return m5_chrROM[(((m5_CHRBank[2]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[3]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1400) + return m5_chrROM[(((m5_CHRBank[4]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1800) + return m5_chrROM[(((m5_CHRBank[5]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1C00) + return m5_chrROM[(((m5_CHRBank[6]<<10)+(addr&0x3FF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[7]<<10)+(addr&0x3FF))&m5_chrROMand)]; + default: + break; + } + } + else + { + switch(m5_chr_bank_mode) + { + case 0: //8KB Pages + return m5_chrROM[(((m5_CHRBank[0xB]<<13)+(addr&0x1FFF))&m5_chrROMand)]; + case 1: //4KB Pages + if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[0xB]<<12)+(addr&0xFFF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[0xB]<<12)+(addr&0xFFF))&m5_chrROMand)]; + case 2: //2KB Pages + if(addr < 0x800) + return m5_chrROM[(((m5_CHRBank[0x9]<<11)+(addr&0x7FF))&m5_chrROMand)]; + if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[0xB]<<11)+(addr&0x7FF))&m5_chrROMand)]; + if(addr < 0x1800) + return m5_chrROM[(((m5_CHRBank[0x9]<<11)+(addr&0x7FF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[0xB]<<11)+(addr&0x7FF))&m5_chrROMand)]; + case 3: //1KB Pages + if(addr < 0x400) + return m5_chrROM[(((m5_CHRBank[0x8]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x800) + return m5_chrROM[(((m5_CHRBank[0x9]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0xC00) + return m5_chrROM[(((m5_CHRBank[0xA]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1000) + return m5_chrROM[(((m5_CHRBank[0xB]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1400) + return m5_chrROM[(((m5_CHRBank[0x8]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1800) + return m5_chrROM[(((m5_CHRBank[0x9]<<10)+(addr&0x3FF))&m5_chrROMand)]; + else if(addr < 0x1C00) + return m5_chrROM[(((m5_CHRBank[0xA]<<10)+(addr&0x3FF))&m5_chrROMand)]; + return m5_chrROM[(((m5_CHRBank[0xB]<<10)+(addr&0x3FF))&m5_chrROMand)]; + default: + break; + } + } + return 0; +} + +void m5chrSet8(uint16_t addr, uint8_t val) +{ + //printf("m5chrSet8 %04x %02x\n", addr, val); + if(m5_chrROM == m5_chrRAM) //Writable + m5_chrROM[addr&0x1FFF] = val; +} + +uint8_t m5vramGet8(uint16_t addr) +{ + if(m5_split && m5_exMode < 2) + { + if((!m5_splitRight && ppuDrawnXTile < m5_splitTile) || + (m5_splitRight && ppuDrawnXTile >= m5_splitTile)) + { + if((addr&0x3FF) < 0x3C0) + return m5_exRAM[ppuDrawnXTile+((m5_irqCtr&~7)<<2)]; + else + return m5_exRAM[0x3C0|((ppuDrawnXTile>>3)+((m5_irqCtr&~15)>>2))]; + } + } + if(addr < 0x800) + return m5_VRAM[addr]; + else if(addr < 0xC00) + { + if(m5_exMode < 2) + return m5_exRAM[addr&0x3FF]; + return 0; + } + else if(addr < 0xFC0) + return m5_fillTile; + return (m5_fillAttr<<0)|(m5_fillAttr<<2)|(m5_fillAttr<<4)|(m5_fillAttr<<6); +} + +void m5vramSet8(uint16_t addr, uint8_t val) +{ + if(addr < 0x800) + m5_VRAM[addr] = val; + else if(addr < 0xC00 && m5_exMode < 2) + m5_exRAM[addr&0x3FF] = val; +} + +uint8_t m5exGetAttrib(uint16_t addr) +{ + return m5_exRAM[addr&0x3FF]>>6; +} + +void m5cycle() +{ + mmc5AudioClockTimers(); + if(ppuInFrame) + { + if(ppuScanlineDone) + { + ppuScanlineDone = false; + if(!m5_inFrame) + { + m5_inFrame = true; + m5_irqCtr = 0; + m5_irqPending = false; + } + else + { + m5_irqCtr++; + if(m5_irqCtr == m5_irqVal) + { + m5_irqPending = true; + //printf("MMC5 IRQ at %i\n", m5_irqCtr); + } + } + } + } + else + m5_inFrame = false; + + if(m5_irqPending && m5_irqEnable) + { + mapper_interrupt = true; + //printf("Beep\n"); + } +} diff --git a/mapperList.c b/mapperList.c index b6d9b76..015c2d3 100644 --- a/mapperList.c +++ b/mapperList.c @@ -11,6 +11,7 @@ #include "mapper_h/m1.h" #include "mapper_h/m4.h" #include "mapper_h/m4add.h" +#include "mapper_h/m5.h" #include "mapper_h/m7.h" #include "mapper_h/m9.h" #include "mapper_h/m10.h" @@ -30,260 +31,260 @@ #include "mapperList.h" mapperList_t mapperList[256] = { - { p32c8init, p32c8get8, m0_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { m1init, m1get8, m1set8, m1chrGet8, m1chrSet8, NULL }, - { p16c8init, p16c8get8, m2_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { p8c8init, p8c8get8, m3_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { m4init, m4get8, m4set8, m4chrGet8, m4chrSet8, m4cycle }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m7init, m7get8, m7set8, m7chrGet8, m7chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m9init, m9get8, m9set8, m9chrGet8, m9chrSet8, NULL }, - { m10init, m10get8, m10set8, m10chrGet8, m10chrSet8, NULL }, - { p32c8init, p32c8get8, m11_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m13init, m13get8, m13set8, m13chrGet8, m13chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m15init, m15get8, m15set8, m15chrGet8, m15chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { vrc2_4_init, vrc2_4_get8, m21_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, vrc2_4_cycle }, - { vrc2_4_init, vrc2_4_get8, m22_set8, m22_chrGet8, vrc2_4_chrSet8, vrc2_4_cycle }, - { vrc2_4_init, vrc2_4_get8, m23_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, vrc2_4_cycle }, - { vrc6init, vrc6get8, m24_set8, vrc6chrGet8, vrc6chrSet8, vrc6cycle }, - { vrc2_4_init, vrc2_4_get8, m25_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, vrc2_4_cycle }, - { vrc6init, vrc6get8, m26_set8, vrc6chrGet8, vrc6chrSet8, vrc6cycle }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m48init, m48get8, m33set8, m48chrGet8, m48chrSet8, NULL }, - { p32c4init, p32c4get8, p32c4set8, p32c4chrGet8, p32c4chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, m36_p32c8get8, m36_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { m37_init, m4get8, m37_set8, m4chrGet8, m4chrSet8, m4cycle }, - { p32c8init, p32c8get8, m38_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m44_init, m4get8, m44_set8, m4chrGet8, m4chrSet8, m4cycle }, - { m45_init, m4get8, m45_set8, m4chrGet8, m4chrSet8, m4cycle }, - { p32c8init, p32c8get8, m46_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { m47_init, m4get8, m47_set8, m4chrGet8, m4chrSet8, m4cycle }, - { m48init, m48get8, m48set8, m48chrGet8, m48chrSet8, m48cycle }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { m52_init, m4get8, m52_set8, m4chrGet8, m4chrSet8, m4cycle }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, m61_get8, m61_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m66_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, p16c8get8, m70_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { p16c8init, p16c8get8, m71_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { vrc1init, vrc1get8, vrc1set8, vrc1chrGet8, vrc1chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, p16c8get8, m78a_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { p32c8init, p32c8get8, m79_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { vrc7init, vrc7get8, vrc7set8, vrc7chrGet8, vrc7chrSet8, vrc7cycle }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p8c8init, p8c8get8, m87_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, p16c8get8, m89_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, p16c8get8, m93_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { p16c8init, p16c8get8, m94_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, m97_get8, m97_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p8c8init, p8c8get8, m99_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p8c8init, p8c8get8, m101_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m113_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m133_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m140_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m144_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { p8c8init, p8c8get8, m145_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { p32c8init, p32c8get8, m79_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { p32c8init, p32c8get8, m147_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { p32c8init, p32c8get8, m148_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { p8c8init, p8c8get8, m149_set8, p8c8chrGet8, p8c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, p16c8get8, m152_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c8init, m180_get8, m180_set8, p16c8chrGet8, p16c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p16c4init, p16c4get8, m184_set8, p16c4chrGet8, p16c4chrSet8, NULL }, - { p8c8init, p8c8get8, m185_set8, m185_chrGet8, p8c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m240_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { p32c8init, p32c8get8, m242_set8, p32c8chrGet8, p32c8chrSet8, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m0_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { m1init, m1get8, m1set8, m1chrGet8, m1chrSet8, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m2_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m3_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { m4init, m4get8, m4set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { m5init, m5get8, m5set8, m5chrGet8, m5chrSet8, m5vramGet8, m5vramSet8, m5cycle }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m7init, m7get8, m7set8, m7chrGet8, m7chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m9init, m9get8, m9set8, m9chrGet8, m9chrSet8, NULL, NULL, NULL }, + { m10init, m10get8, m10set8, m10chrGet8, m10chrSet8, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m11_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m13init, m13get8, m13set8, m13chrGet8, m13chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m15init, m15get8, m15set8, m15chrGet8, m15chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { vrc2_4_init, vrc2_4_get8, m21_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, NULL, NULL, vrc2_4_cycle }, + { vrc2_4_init, vrc2_4_get8, m22_set8, m22_chrGet8, vrc2_4_chrSet8, NULL, NULL, vrc2_4_cycle }, + { vrc2_4_init, vrc2_4_get8, m23_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, NULL, NULL, vrc2_4_cycle }, + { vrc6init, vrc6get8, m24_set8, vrc6chrGet8, vrc6chrSet8, NULL, NULL, vrc6cycle }, + { vrc2_4_init, vrc2_4_get8, m25_set8, vrc2_4_chrGet8, vrc2_4_chrSet8, NULL, NULL, vrc2_4_cycle }, + { vrc6init, vrc6get8, m26_set8, vrc6chrGet8, vrc6chrSet8, NULL, NULL, vrc6cycle }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m48init, m48get8, m33set8, m48chrGet8, m48chrSet8, NULL, NULL, NULL }, + { p32c4init, p32c4get8, p32c4set8, p32c4chrGet8, p32c4chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, m36_p32c8get8, m36_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { m37_init, m4get8, m37_set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { p32c8init, p32c8get8, m38_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m44_init, m4get8, m44_set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { m45_init, m4get8, m45_set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { p32c8init, p32c8get8, m46_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { m47_init, m4get8, m47_set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { m48init, m48get8, m48set8, m48chrGet8, m48chrSet8, NULL, NULL, m48cycle }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m52_init, m4get8, m52_set8, m4chrGet8, m4chrSet8, NULL, NULL, m4cycle }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, m61_get8, m61_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m66_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m70_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m71_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { vrc1init, vrc1get8, vrc1set8, vrc1chrGet8, vrc1chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m78a_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m79_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { vrc7init, vrc7get8, vrc7set8, vrc7chrGet8, vrc7chrSet8, NULL, NULL, vrc7cycle }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m87_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m89_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m93_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m94_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, m97_get8, m97_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m99_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m101_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m113_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m133_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m140_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m144_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m145_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m79_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m147_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m148_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m149_set8, p8c8chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, p16c8get8, m152_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c8init, m180_get8, m180_set8, p16c8chrGet8, p16c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p16c4init, p16c4get8, m184_set8, p16c4chrGet8, p16c4chrSet8, NULL, NULL, NULL }, + { p8c8init, p8c8get8, m185_set8, m185_chrGet8, p8c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m240_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { p32c8init, p32c8get8, m242_set8, p32c8chrGet8, p32c8chrSet8, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, }; diff --git a/mapperList.h b/mapperList.h index 1f0e307..8466623 100644 --- a/mapperList.h +++ b/mapperList.h @@ -14,6 +14,8 @@ typedef struct _mapperList_t { set8FuncT set8F; chrGet8FuncT chrGet8F; chrSet8FuncT chrSet8F; + vramGet8FuncT vramGet8F; + vramSet8FuncT vramSet8F; cycleFuncT cycleFuncF; } mapperList_t; diff --git a/mapper_h/m5.h b/mapper_h/m5.h new file mode 100644 index 0000000..5c3fe7f --- /dev/null +++ b/mapper_h/m5.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2017 FIX94 + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef m5_h_ +#define m5_h_ + +void m5init(uint8_t *prgROM, uint32_t prgROMsize, + uint8_t *prgRAM, uint32_t prgRAMsize, + uint8_t *chrROM, uint32_t chrROMsize); +uint8_t m5get8(uint16_t addr, uint8_t val); +void m5set8(uint16_t addr, uint8_t val); +uint8_t m5chrGet8(uint16_t addr); +void m5chrSet8(uint16_t addr, uint8_t val); +uint8_t m5vramGet8(uint16_t addr); +void m5vramSet8(uint16_t addr, uint8_t val); +void m5cycle(); + +#endif diff --git a/ppu.c b/ppu.c index 11ca437..762b0fc 100644 --- a/ppu.c +++ b/ppu.c @@ -50,6 +50,10 @@ //set or used externally bool ppu4Screen = false; +bool ppu816Sprite = false; +bool ppuInFrame = false; +bool ppuScanlineDone = false; +uint8_t ppuDrawnXTile = 0; //from main.c extern uint32_t textureImage[0xF000]; @@ -74,7 +78,7 @@ static const uint8_t PPU_Pal[192] = } ; static uint8_t PPU_Reg[8]; -static uint8_t PPU_VRAM[0x2000]; +static uint8_t PPU_VRAM[0x1000]; static uint8_t PPU_OAM[0x100]; static uint8_t PPU_OAM2[0x20]; @@ -125,7 +129,7 @@ extern bool nesPAL; void ppuInit() { memset(PPU_Reg,0,8); - memset(PPU_VRAM,0,0x2000); + memset(PPU_VRAM,0,0x1000); memset(PPU_OAM,0,0x100); memset(PPU_PALRAM,0,0x20); memset(PPU_OAM2,0xFF,0x20); @@ -192,6 +196,8 @@ void ppuInit() } } +extern uint8_t m5_exMode; +extern uint8_t m5exGetAttrib(uint16_t addr); static inline uint16_t ppuGetVramTbl(uint16_t tblStart) { return ppuNameTbl[(tblStart>>10)&3]; @@ -207,43 +213,69 @@ bool ppuCycle() bool pictureOutput = (PPU_Reg[1] & (PPU_BG_ENABLE | PPU_SPRITE_ENABLE)) != 0; + /* For MMC5 Scanline Detect */ + if(curDot == 0) + { + if((curLine <= VISIBLE_LINES) && pictureOutput) + { + ppuInFrame = true; + ppuScanlineDone = true; + } + else + ppuInFrame = false; + } /* Do Background Updates */ if((curLine == ppuPreRenderLine || curLine < VISIBLE_LINES)) { /* Do BG Reg Updates every 8 dots */ if((curDot & 7) == 0 && (curDot >= 319 || (curDot && curDot <= VISIBLE_DOTS))) { - uint16_t cPpuTbl = ppuGetVramTbl(ppuVramAddr); - /* Select new BG Background Attribute */ - uint8_t cAttrib = ((ppuVramAddr>>4)&0x38) | ((ppuVramAddr>>2)&7); - uint16_t attributeAddr = cPpuTbl | (0x3C0 | cAttrib); - uint8_t cPalByte = PPU_VRAM[attributeAddr]; - bool left = ((ppuVramAddr&2) == 0); - //top tiles - if((ppuVramAddr&0x40) == 0) + /* MMC5 Scroll Related */ + if(curDot == 320) + ppuDrawnXTile = 0; + else + ppuDrawnXTile++; + if(m5_exMode == 1) { - if(left) - { - ppuBGAttribValA = (cPalByte)&1; - ppuBGAttribValB = (cPalByte>>1)&1; - } - else - { - ppuBGAttribValA = (cPalByte>>2)&1; - ppuBGAttribValB = (cPalByte>>3)&1; - } + /* MMC5 Ex Mode 1 has different Attribute for every Tile */ + uint8_t cPalByte = m5exGetAttrib(ppuVramAddr); + ppuBGAttribValA = (cPalByte)&1; + ppuBGAttribValB = (cPalByte>>1)&1; } - else //bottom tiles + else { - if(left) + uint16_t cPpuTbl = ppuGetVramTbl(ppuVramAddr); + /* Select new BG Background Attribute */ + uint8_t cAttrib = ((ppuVramAddr>>4)&0x38) | ((ppuVramAddr>>2)&7); + uint16_t attributeAddr = cPpuTbl | (0x3C0 | cAttrib); + uint8_t cPalByte = mapperVramGet8(attributeAddr); + bool left = ((ppuVramAddr&2) == 0); + //top tiles + if((ppuVramAddr&0x40) == 0) { - ppuBGAttribValA = (cPalByte>>4)&1; - ppuBGAttribValB = (cPalByte>>5)&1; + if(left) + { + ppuBGAttribValA = (cPalByte)&1; + ppuBGAttribValB = (cPalByte>>1)&1; + } + else + { + ppuBGAttribValA = (cPalByte>>2)&1; + ppuBGAttribValB = (cPalByte>>3)&1; + } } - else + else //bottom tiles { - ppuBGAttribValA = (cPalByte>>6)&1; - ppuBGAttribValB = (cPalByte>>7)&1; + if(left) + { + ppuBGAttribValA = (cPalByte>>4)&1; + ppuBGAttribValB = (cPalByte>>5)&1; + } + else + { + ppuBGAttribValA = (cPalByte>>6)&1; + ppuBGAttribValB = (cPalByte>>7)&1; + } } } if(curDot == 328) @@ -306,9 +338,10 @@ bool ppuCycle() /* Select new BG Tiles */ uint16_t chrROMBG = (PPU_Reg[0] & PPU_BACKGROUND_ADDR) ? 0x1000 : 0; uint16_t workAddr = cPpuTbl | (ppuVramAddr & 0x3FF); - uint8_t curBGtileReg = PPU_VRAM[workAddr]; + uint8_t curBGtileReg = mapperVramGet8(workAddr); uint8_t curTileY = (ppuVramAddr>>12)&7; uint16_t curBGTile = chrROMBG+(curBGtileReg<<4)+curTileY; + mapperChrMode = 0; ppuBGValA = mapperChrGet8(curBGTile); ppuBGValB = mapperChrGet8(curBGTile+8); } @@ -449,7 +482,8 @@ bool ppuCycle() if(PPU_Reg[0] & PPU_SPRITE_8_16) cSpriteAdd ^= 16; //8 by 16 select } - /* write processed values into internal draw buffer */ + /* write processed values into internal draw buffer */ + mapperChrMode = 1; PPU_Sprites[ppuSpriteTilePos] = mapperChrGet8(((chrROMSpriteAdd+(cSpriteIndex<<4)+cSpriteY+cSpriteAdd)&0xFFF) | chrROMSpriteAdd); PPU_Sprites[ppuSpriteTilePos+1] = mapperChrGet8(((chrROMSpriteAdd+(cSpriteIndex<<4)+cSpriteY+8+cSpriteAdd)&0xFFF) | chrROMSpriteAdd); PPU_Sprites[ppuSpriteTilePos+2] = cSpriteByte2; @@ -610,6 +644,7 @@ void ppuSet8(uint8_t reg, uint8_t val) PPU_Reg[reg] = val; ppuTmpVramAddr &= ~0xC00; ppuTmpVramAddr |= ((val&3)<<10); + ppu816Sprite = (PPU_Reg[0] & PPU_SPRITE_8_16) != 0; //printf("%d %d %d\n", (PPU_Reg[0] & PPU_BACKGROUND_ADDR) != 0, (PPU_Reg[0] & PPU_SPRITE_ADDR) != 0, (PPU_Reg[0] & PPU_SPRITE_8_16) != 0); } else if(reg == 3) @@ -675,7 +710,7 @@ void ppuSet8(uint8_t reg, uint8_t val) { uint16_t workAddr = ppuGetVramTbl(writeAddr) | (writeAddr & 0x3FF); //printf("ppuVRAMwrite %04x %02x\n", workAddr, val); - PPU_VRAM[workAddr] = val; + mapperVramSet8(workAddr, val); } else { @@ -713,13 +748,14 @@ uint8_t ppuGet8(uint8_t reg) if(writeAddr < 0x2000) { ret = ppuVramReadBuf; + mapperChrMode = 2; ppuVramReadBuf = mapperChrGet8(writeAddr); } else if(writeAddr < 0x3F00) { ret = ppuVramReadBuf; uint16_t workAddr = ppuGetVramTbl(writeAddr) | (writeAddr & 0x3FF); - ppuVramReadBuf = PPU_VRAM[workAddr]; + ppuVramReadBuf = mapperVramGet8(workAddr); //printf("ppuVRAMread pc %04x addr %04x ret %02x\n", cpuGetPc(), workAddr, ret); } else @@ -730,7 +766,7 @@ uint8_t ppuGet8(uint8_t reg) ret = PPU_PALRAM[palRamAddr]&((PPU_Reg[1]&PPU_GRAY)?0x30:0x3F); //shadow read uint16_t workAddr = ppuGetVramTbl(writeAddr) | (writeAddr & 0x3FF); - ppuVramReadBuf = PPU_VRAM[workAddr]; + ppuVramReadBuf = mapperVramGet8(workAddr); } ppuVramAddr += (PPU_Reg[0] & PPU_INC_AMOUNT) ? 32 : 1; } @@ -768,7 +804,7 @@ void ppuDumpMem() FILE *f = fopen("PPU_VRAM.bin","wb"); if(f) { - fwrite(PPU_VRAM,1,0x800,f); + fwrite(PPU_VRAM,1,0x1000,f); fclose(f); } f = fopen("PPU_OAM.bin","wb"); @@ -916,3 +952,13 @@ void ppuDrawNSFTrackNum(uint8_t cTrack, uint8_t trackTotal) ppuDrawRest(curX, trackTotal%10); curX+=10; } + +uint8_t ppuVRAMGet8(uint16_t addr) +{ + return PPU_VRAM[addr&0xFFF]; +} + +void ppuVRAMSet8(uint16_t addr, uint8_t val) +{ + PPU_VRAM[addr&0xFFF] = val; +} diff --git a/ppu.h b/ppu.h index de87038..0eccc4a 100644 --- a/ppu.h +++ b/ppu.h @@ -27,6 +27,9 @@ void ppuSetNameTblCustom(uint16_t addrA, uint16_t addrB, uint16_t addrC, uint16_ void ppuDrawNSFTrackNum(uint8_t cTrack, uint8_t trackTotal); +uint8_t ppuVRAMGet8(uint16_t addr); +void ppuVRAMSet8(uint16_t addr, uint8_t val); + extern bool ppu4Screen; #endif