From 8656faa9b1d0b723695911abc4510030366a534e Mon Sep 17 00:00:00 2001 From: FIX94 Date: Wed, 16 Jan 2019 19:24:48 +0100 Subject: [PATCH] -slightly reduced default volume to reduce potential clipping -implemented mapper 30, should work in both flashable and non-flashable configurations --- README.md | 2 +- apu.c | 6 +- main.c | 33 ++++-- mapper/m30.c | 300 +++++++++++++++++++++++++++++++++++++++++++++++++ mapperList.c | 5 +- mapper_h/m30.h | 18 +++ 6 files changed, 351 insertions(+), 13 deletions(-) create mode 100644 mapper/m30.c create mode 100644 mapper_h/m30.h diff --git a/README.md b/README.md index 8104b6e..fb5c394 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ To start a file, simply drag and drop it into the fixNES Application or call it You can also load from a .zip file, the first found supported file from that .zip will be used. Supported .nes Mappers: -0,1,2,3,4,5,7,9,10,11,12,13,15,19,21,22,23,24,25,26,28,31,32,33,34,36,37,38,41,44,45,46,47,48,49,52,57,58,60,61,62,65,66,67,68,69,70,71,73,75,76,78,79,85,87,88,89,93,94,95,97,101,107,112,113,118,119,132,133,136,137,138,139,140,141,144,145,146,147,148,149,152,154,155,156,172,173,174,180,184,185,193,200,201,202,203,205,206,210,212,221,225,226,228,229,230,231,232,235,237,240 and 242. +0,1,2,3,4,5,7,9,10,11,12,13,15,19,21,22,23,24,25,26,28,30,31,32,33,34,36,37,38,41,44,45,46,47,48,49,52,57,58,60,61,62,65,66,67,68,69,70,71,73,75,76,78,79,85,87,88,89,93,94,95,97,101,107,112,113,118,119,132,133,136,137,138,139,140,141,144,145,146,147,148,149,152,154,155,156,172,173,174,180,184,185,193,200,201,202,203,205,206,210,212,221,225,226,228,229,230,231,232,235,237,240 and 242. Supported Audio Expansions (for both ROMs and NSF Files): VRC6, VRC7, FDS, MMC5, N163, Sunsoft 5B diff --git a/apu.c b/apu.c index 2e582d1..387e82e 100644 --- a/apu.c +++ b/apu.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 - 2018 FIX94 + * Copyright (C) 2017 - 2019 FIX94 * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. @@ -110,9 +110,9 @@ static struct { } apu; #if AUDIO_FLOAT -static float APU_ampVol[7] = { 3.0f, 2.0f, 1.5f, 1.2f, 1.0f, 0.85f, 0.75f }; +static float APU_ampVol[7] = { 2.0f, 1.75f, 1.5f, 1.2f, 1.0f, 0.85f, 0.75f }; #else -static int32_t APU_ampVol[7] = { 192, 128, 96, 77, 64, 55, 48 }; +static int32_t APU_ampVol[7] = { 128, 112, 96, 77, 64, 55, 48 }; #endif //used externally diff --git a/main.c b/main.c index 8081d8a..5fbed38 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 - 2018 FIX94 + * Copyright (C) 2017 - 2019 FIX94 * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. @@ -38,7 +38,7 @@ #define DEBUG_KEY 0 #define DEBUG_LOAD_INFO 1 -const char *VERSION_STRING = "fixNES Alpha v1.2.3"; +const char *VERSION_STRING = "fixNES Alpha v1.2.4"; static char window_title[256]; static char window_title_pause[256]; @@ -143,6 +143,9 @@ uint32_t cpuCycleTimer; uint32_t vrc7CycleTimer; //from input.c extern uint8_t inValReads[8]; +//from m30.c +extern bool m30_flashable; +extern bool m30_singlescreen; //from m32.c extern bool m32_singlescreen; //from p16c8.c @@ -223,16 +226,27 @@ int main(int argc, char** argv) printf("Suggested CHR ROM of 0x%04x is too big, using 0x%04x instead\n", chrROMsize, ROMsize); chrROMsize = ROMsize; } - if(mapper == 5) //just to be on the safe side - emuPrgRAMsize = 0x10000; + if(mapper == 30 && emuSaveEnabled) //rewritable prg + { + emuPrgRAMsize = prgROMsize; + m30_flashable = true; + } else { - emuPrgRAMsize = emuNesROM[8] * 0x2000; - if(emuPrgRAMsize == 0) emuPrgRAMsize = 0x2000; + m30_flashable = false; + 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) + if(m30_flashable) //initial prg fill + memcpy(emuPrgRAM, prgROM, prgROMsize); + else if(trainer) { memcpy(emuPrgRAM+0x1000,prgROM,0x200); prgROM += 512; @@ -270,6 +284,11 @@ int main(int argc, char** argv) #endif if(mapper == 5) ppuMapper5 = true; + else if(mapper == 30) + { + //TODO: add single screen ones here + m30_singlescreen = false; + } else if(mapper == 32) { if(strstr(emuFileName,"Major League") != NULL) diff --git a/mapper/m30.c b/mapper/m30.c new file mode 100644 index 0000000..fd77783 --- /dev/null +++ b/mapper/m30.c @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2019 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 "../mem.h" +#include "../mapper_h/common.h" + +//sector erase and byte write +enum { + //get erase/write cmd + M30_STATE_C0_INIT = 0, + M30_STATE_80_INIT, + M30_STATE_C1_INIT, + M30_STATE_81_INIT, + M30_STATE_C2_INIT, + M30_STATE_82_INIT, + //erase cmd check + M30_STATE_C3_DEL, + M30_STATE_83_DEL, + M30_STATE_C4_DEL, + M30_STATE_84_DEL, + //erase cmd execute + M30_STATE_C5_DEL, + M30_STATE_85_DEL, + //write cmd execute + M30_STATE_C3_WRI, + M30_STATE_83_WRI, +}; + +static struct { + uint8_t chrRAM[0x8000]; + uint8_t *chrRAMBankPtr; + uint8_t *prgRAMptr; + uint8_t *prgRAMBankPtr; + uint32_t prgRAMsize; + uint32_t prgRAMand; + uint8_t step, manID, devID; + bool software_id; +} m30; +//used externally +bool m30_flashable; +bool m30_singlescreen; + +void m30init(uint8_t *prgROMin, uint32_t prgROMsizeIn, + uint8_t *prgRAMin, uint32_t prgRAMsizeIn, + uint8_t *chrROMin, uint32_t chrROMsizeIn) +{ + if(m30_flashable) + { + m30.prgRAMptr = prgRAMin; + m30.prgRAMBankPtr = m30.prgRAMptr; + m30.prgRAMsize = prgRAMsizeIn; + m30.prgRAMand = mapperGetAndValue(prgRAMsizeIn); + prg16init(prgRAMin, prgRAMsizeIn); + prg16setBank1(prgRAMsizeIn - 0x4000); + m30.step = M30_STATE_C0_INIT; //sequence progress + m30.software_id = false; //replaces 8000/8001 + m30.manID = 0xBF; //SST, Device ID Below + m30.devID = (prgRAMsizeIn == 0x20000 ? 0xB5 : (prgRAMsizeIn == 0x40000 ? 0xB6 : (prgRAMsizeIn == 0x80000 ? 0xB7 : 0))); + printf("Mapper 30 flashable, Man ID %02x Dev ID %02x\n", m30.manID, m30.devID); + } + else + { + m30.prgRAMptr = NULL, m30.prgRAMBankPtr = NULL; + m30.prgRAMsize = 0; + prg16init(prgROMin, prgROMsizeIn); + prg16setBank1(prgROMsizeIn - 0x4000); + printf("Mapper 30 not flashable\n"); + } + (void)chrROMin; (void)chrROMsizeIn; + m30.chrRAMBankPtr = m30.chrRAM; + if(m30_singlescreen) + ppuSetNameTblSingleLower(); + printf("Mapper 30 inited\n"); +} + +static void m30setParamsNoFlash(uint16_t addr, uint8_t val) +{ + (void)addr; + prg16setBank0((val&0x1F)<<14); + m30.chrRAMBankPtr = m30.chrRAM+((val&0x60)<<8); + if(m30_singlescreen) + { + if(val & 0x80) + ppuSetNameTblSingleUpper(); + else + ppuSetNameTblSingleLower(); + } +} + +static uint8_t m30GetId0(uint16_t addr) { (void)addr; return m30.manID; } +static uint8_t m30GetId1(uint16_t addr) { (void)addr; return m30.devID; } + +static void m30sidEntry() +{ + //printf("M30 Software ID CMD Entry\n"); + m30.software_id = true; + memInitMapperGetPointer(0x8000, m30GetId0); + memInitMapperGetPointer(0x8001, m30GetId1); +} + +static void m30sidExit() +{ + //printf("M30 Software ID CMD Exit\n"); + m30.software_id = false; + prg16initGet8(0x8000); + prg16initGet8(0x8001); +} + +static void m30setParams8000(uint16_t addr, uint8_t val) +{ + //printf("%04x %02x\n", addr, val); + if(val == 0xF0 && m30.software_id) + m30sidExit(); + switch(m30.step) + { + //initial cmd check + case M30_STATE_80_INIT: + if(addr == 0x9555 && val == 0xAA) + m30.step = M30_STATE_C1_INIT; + else goto _8000_step_reset; + break; + case M30_STATE_81_INIT: + if(addr == 0xAAAA && val == 0x55) + m30.step = M30_STATE_C2_INIT; + else goto _8000_step_reset; + break; + case M30_STATE_82_INIT: + if(addr == 0x9555 && val == 0x80) + { + //printf("M30 Erase CMD\n"); + m30.step = M30_STATE_C3_DEL; + } + else if(addr == 0x9555 && val == 0xA0) + { + //printf("M30 Write CMD\n"); + m30.step = M30_STATE_C3_WRI; + } + else + { + if(addr == 0x9555 && val == 0x90 && !m30.software_id) + m30sidEntry(); + //redundant since any address exits software id? + //else if(addr == 0x9555 && val == 0xF0 && m30.software_id) + // m30sidExit(); + goto _8000_step_reset; + } + break; + //delete cmd check + case M30_STATE_83_DEL: + if(addr == 0x9555 && val == 0xAA) + m30.step = M30_STATE_C4_DEL; + else goto _8000_step_reset; + break; + case M30_STATE_84_DEL: + if(addr == 0xAAAA && val == 0x55) + m30.step = M30_STATE_C5_DEL; + else goto _8000_step_reset; + break; + //executes delete + case M30_STATE_85_DEL: + if(addr == 0x9555 && val == 0x10) //full erase + { + //printf("M30 Full Erase\n"); + if(m30.prgRAMptr && m30.prgRAMsize) + memset(m30.prgRAMptr, 0xFF, m30.prgRAMsize); + } + else if(val == 30) //sector erase + { + //printf("M30 Sector Erase %04x\n", (addr&0x7000)); + if(m30.prgRAMBankPtr) + memset(m30.prgRAMBankPtr+(addr&0x7000), 0xFF, 0x1000); + } + goto _8000_step_reset; + //executes write + case M30_STATE_83_WRI: + if(m30.prgRAMBankPtr) //byte write + { + //printf("M30 Byte Write %04x %02x\n", addr&0x7FFF, val); + m30.prgRAMBankPtr[addr&0x7FFF] = val; + } + goto _8000_step_reset; + //any other state or state verify fail + //will result in a command reset + default: + _8000_step_reset: + m30.step = M30_STATE_C0_INIT; + break; + } +} + +static void m30setParamsC000(uint16_t addr, uint8_t val) +{ + //printf("%04x %02x\n", addr, val); + m30setParamsNoFlash(addr, val); + if(val == 0xF0 && m30.software_id) + m30sidExit(); + switch(m30.step) + { + //initial cmd check + case M30_STATE_C0_INIT: + if(addr == 0xC000 && val == 1) + m30.step = M30_STATE_80_INIT; + break; + case M30_STATE_C1_INIT: + if(addr == 0xC000 && val == 0) + m30.step = M30_STATE_81_INIT; + else goto c000_step_reset; + break; + case M30_STATE_C2_INIT: + if(addr == 0xC000 && val == 1) + m30.step = M30_STATE_82_INIT; + else goto c000_step_reset; + break; + //delete cmd check + case M30_STATE_C3_DEL: + if(addr == 0xC000 && val == 1) + m30.step = M30_STATE_83_DEL; + else goto c000_step_reset; + break; + case M30_STATE_C4_DEL: + if(addr == 0xC000 && val == 0) + m30.step = M30_STATE_84_DEL; + else goto c000_step_reset; + break; + //executes delete + case M30_STATE_C5_DEL: + if(addr == 0xC000 && val < 0x20) + { + m30.step = M30_STATE_85_DEL; + if(m30.prgRAMptr) //for memset + { + //printf("M30 Delete Bank %04x\n", val); + m30.prgRAMBankPtr = m30.prgRAMptr+((val<<14)&m30.prgRAMand); + } + } + else goto c000_step_reset; + break; + //executes write + case M30_STATE_C3_WRI: + if(addr == 0xC000 && val < 0x20) + { + m30.step = M30_STATE_83_WRI; + if(m30.prgRAMptr) //for byte write + { + //printf("M30 Write Bank %04x\n", val); + m30.prgRAMBankPtr = m30.prgRAMptr+((val<<14)&m30.prgRAMand); + } + } + else goto c000_step_reset; + break; + //any other state or state verify fail + //will result in a command reset + default: + c000_step_reset: + //immediately do M30_STATE_C0_INIT check + if(addr == 0xC000 && val == 1) + m30.step = M30_STATE_80_INIT; + else //different values, full reset + m30.step = M30_STATE_C0_INIT; + break; + } +} + +void m30initSet8(uint16_t addr) +{ + if(addr < 0x8000) return; + if(m30_flashable) + { + if(addr < 0xC000) + memInitMapperSetPointer(addr, m30setParams8000); + else + memInitMapperSetPointer(addr, m30setParamsC000); + } + else + memInitMapperSetPointer(addr, m30setParamsNoFlash); +} + +static uint8_t m30ChrGetRAM(uint16_t addr) { return m30.chrRAMBankPtr[addr]; } +void m30initPPUGet8(uint16_t addr) +{ + if(addr < 0x2000) + memInitMapperPPUGetPointer(addr, m30ChrGetRAM); +} + +static void m30ChrSetRAM(uint16_t addr, uint8_t val) { m30.chrRAMBankPtr[addr] = val; } +void m30initPPUSet8(uint16_t addr) +{ + if(addr < 0x2000) + memInitMapperPPUSetPointer(addr, m30ChrSetRAM); +} diff --git a/mapperList.c b/mapperList.c index d4fd2fc..cc2c6c7 100644 --- a/mapperList.c +++ b/mapperList.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 - 2018 FIX94 + * Copyright (C) 2017 - 2019 FIX94 * * This software may be modified and distributed under the terms * of the MIT license. See the LICENSE file for details. @@ -16,6 +16,7 @@ #include "mapper_h/m13.h" #include "mapper_h/m15.h" #include "mapper_h/m28.h" +#include "mapper_h/m30.h" #include "mapper_h/m31.h" #include "mapper_h/m32.h" #include "mapper_h/m33.h" @@ -78,7 +79,7 @@ mapperList_t mapperList[256] = { { NULL, NULL, NULL, NULL, NULL, NULL, NULL }, { m28init, m28initGet8, m28initSet8, m28initPPUGet8, m28initPPUSet8, NULL, NULL }, { NULL, NULL, NULL, NULL, NULL, NULL, NULL }, - { NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + { m30init, prg16initGet8, m30initSet8, m30initPPUGet8, m30initPPUSet8, NULL, NULL }, { m31init, prg4initGet8, m31initSet8, chr8initPPUGet8, chr8initPPUSet8, NULL, NULL }, { m32init, m32initGet8, m32initSet8, chr1initPPUGet8, chr1initPPUSet8, NULL, NULL }, { m33init, prg8initGet8, m33initSet8, chr1initPPUGet8, chr1initPPUSet8, NULL, NULL }, diff --git a/mapper_h/m30.h b/mapper_h/m30.h new file mode 100644 index 0000000..cadbb23 --- /dev/null +++ b/mapper_h/m30.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2019 FIX94 + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + */ + +#ifndef m30_h_ +#define m30_h_ + +void m30init(uint8_t *prgROM, uint32_t prgROMsize, + uint8_t *prgRAM, uint32_t prgRAMsize, + uint8_t *chrROM, uint32_t chrROMsize); +void m30initSet8(uint16_t addr); +void m30initPPUGet8(uint16_t addr); +void m30initPPUSet8(uint16_t addr); + +#endif