From 25c0b96c30d5a43bf3e5dc74abec751b3b9d6d97 Mon Sep 17 00:00:00 2001 From: g0me3 Date: Fri, 25 Oct 2019 20:52:08 +0300 Subject: [PATCH 01/15] mapper 547 (ines 2.0 version of KONAMI-QTAi UNIF board) --- src/boards/vrc5.cpp | 10 +++++----- src/ines.cpp | 12 ++++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/boards/vrc5.cpp b/src/boards/vrc5.cpp index 4dc903eb..07de8010 100644 --- a/src/boards/vrc5.cpp +++ b/src/boards/vrc5.cpp @@ -152,11 +152,11 @@ static void Sync(void) { chrSync(); setprg4r(0x10, 0x6000, (regs[0] & 1) | (regs[0] >> 2)); // two 4K banks are identical, either internal or excernal setprg4r(0x10, 0x7000, (regs[1] & 1) | (regs[1] >> 2)); // SRAMs may be mapped in any bank independently - if (PRGsize[0] == 1024 * 1024) {// hacky hacky way to run it as iNES rom for debugging purposes - setprg8(0x8000, regs[2]); - setprg8(0xA000, regs[3]); - setprg8(0xC000, regs[4]); - setprg8(0xE000, ~0); + if (PRGptr[1] == NULL) { // for iNES 2.0 version it even more hacky lol + setprg8(0x8000, (regs[2] & 0x3F) + ((regs[2] & 0x40) >> 2)); + setprg8(0xA000, (regs[3] & 0x3F) + ((regs[3] & 0x40) >> 2)); + setprg8(0xC000, (regs[4] & 0x3F) + ((regs[4] & 0x40) >> 2)); + setprg8(0xE000, 0x10 + 0x3F); } else { setprg8r((regs[2] >> 6) & 1, 0x8000, (regs[2] & 0x3F)); setprg8r((regs[3] >> 6) & 1, 0xA000, (regs[3] & 0x3F)); diff --git a/src/ines.cpp b/src/ines.cpp index 89da3c6b..97e28f6b 100644 --- a/src/ines.cpp +++ b/src/ines.cpp @@ -439,9 +439,16 @@ typedef struct { //that are not in the power of 2 tends to come //in obscure mappers themselves which supports such //size +//Cah4e3 25.10.19: iNES 2.0 attempts to cover all +// boards including UNIF boards with non power 2 +// total rom size (a lot of them with a couple of +// roms different sizes (may vary a lot) +// so we need either add here ALL ines 2.0 mappers +// with not power2 roms or change logic here +// to something more unified for ines 2.0 specific static int not_power2[] = { - 53, 198, 228 + 53, 198, 228, 547 }; BMAPPINGLocal bmap[] = { @@ -716,7 +723,8 @@ BMAPPINGLocal bmap[] = { {"158B Prot Board", 258, UNL158B_Init}, {"F-15 MMC3 Based", 259, BMCF15_Init}, {"HP10xx/H20xx Boards", 260, BMCHPxx_Init}, - {"810544-CA-1", 261, BMC810544CA1_Init}, + {"810544-CA-1", 261, BMC810544CA1_Init}, + { "KONAMI QTAi Board", 547, QTAi_Init }, {"", 0, NULL} }; From 5c8421d410573f11370c545ae13235f116bf5137 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 8 Nov 2019 00:03:31 -0500 Subject: [PATCH 02/15] Palette mirror fix (#81) * ppuview and memview fixes for palette mirroring * New PPU $2001 rendering off palette mirroring fixed --- src/debug.h | 2 +- src/drivers/win/memview.cpp | 31 +++++++++++++++++++++++++++---- src/drivers/win/ppuview.cpp | 22 +++++++++++----------- src/ppu.cpp | 2 +- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/debug.h b/src/debug.h index 21aa3774..9c25b376 100644 --- a/src/debug.h +++ b/src/debug.h @@ -113,7 +113,7 @@ extern void IncrementInstructionsCounters(); //internal variables that debuggers will want access to extern uint8 *vnapage[4],*VPage[8]; -extern uint8 PPU[4],PALRAM[0x20],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset; +extern uint8 PPU[4],PALRAM[0x20],UPALRAM[3],SPRAM[0x100],VRAMBuffer,PPUGenLatch,XOffset; extern uint32 FCEUPPU_PeekAddress(); extern uint8 READPAL_MOTHEROFALL(uint32 A); extern int numWPs; diff --git a/src/drivers/win/memview.cpp b/src/drivers/win/memview.cpp index 60ef4f35..682ba7cf 100644 --- a/src/drivers/win/memview.cpp +++ b/src/drivers/win/memview.cpp @@ -147,6 +147,7 @@ void FindNext(); void OpenFindDialog(); static int GetFileData(uint32 offset); static int WriteFileData(uint32 offset,int data); +static void PalettePoke(uint32 addr, uint8 data); HWND hMemView, hMemFind; @@ -1013,7 +1014,7 @@ void InputData(char *input){ if((addr >= 0x2000) && (addr < 0x3F00)) vnapage[(addr>>10)&0x3][addr&0x3FF] = data[i]; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? if((addr >= 0x3F00) && (addr < 0x3FFF)) - PALRAM[addr&0x1F] = data[i]; + PalettePoke(addr,data[i]); } else if (EditingMode == MODE_NES_OAM) { addr &= 0xFF; @@ -1049,7 +1050,7 @@ if(EditingMode == MODE_NES_PPU){ addr &= 0x3FFF; if(addr < 0x2000)VPage[addr>>10][addr] = data; //todo: detect if this is vrom and turn it red if so if((addr > 0x2000) && (addr < 0x3F00))vnapage[(addr>>10)&0x3][addr&0x3FF] = data; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? -if((addr > 0x3F00) && (addr < 0x3FFF))PALRAM[addr&0x1F] = data; +if((addr > 0x3F00) && (addr < 0x3FFF)) PalettePoke(addr,data); } if(EditingMode == MODE_NES_FILE)ApplyPatch(addr,1,(uint8 *)&data); CursorStartAddy++; @@ -1915,7 +1916,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa i &= 0x3FFF; if(i < 0x2000) bar[i] = VPage[(i)>>10][(i)]; else if(i < 0x3F00) bar[i] = vnapage[(i>>10)&0x3][i&0x3FF]; - else bar[i] = PALRAM[i&0x1F]; + else bar[i] = READPAL_MOTHEROFALL(i & 0x1F); } dumpToFile(bar, sizeof(bar)); return 0; @@ -1952,7 +1953,7 @@ LRESULT CALLBACK MemViewCallB(HWND hwnd, UINT message, WPARAM wParam, LPARAM lPa if((addr >= 0x2000) && (addr < 0x3F00)) vnapage[(addr>>10)&0x3][addr&0x3FF] = v; //todo: this causes 0x3000-0x3f00 to mirror 0x2000-0x2f00, is this correct? if((addr >= 0x3F00) && (addr < 0x3FFF)) - PALRAM[addr&0x1F] = v; + PalettePoke(addr,v); } } return 0; @@ -2394,3 +2395,25 @@ void OpenFindDialog() hMemFind = CreateDialog(fceu_hInstance,"MEMVIEWFIND",hMemView,MemFindCallB); return; } + +void PalettePoke(uint32 addr, uint8 data) +{ + data = data & 0x3F; + addr = addr & 0x1F; + if ((addr & 3) == 0) + { + addr = (addr & 0xC) >> 2; + if (addr == 0) + { + PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = data; + } + else + { + UPALRAM[addr-1] = UPALRAM[0x10|(addr-1)] = data; + } + } + else + { + PALRAM[addr] = data; + } +} diff --git a/src/drivers/win/ppuview.cpp b/src/drivers/win/ppuview.cpp index 140c94fe..95dbb55a 100644 --- a/src/drivers/win/ppuview.cpp +++ b/src/drivers/win/ppuview.cpp @@ -29,13 +29,15 @@ HWND hPPUView; extern uint8 *VPage[8]; extern uint8 PALRAM[0x20]; +extern uint8 UPALRAM[3]; int PPUViewPosX, PPUViewPosY; bool PPUView_maskUnusedGraphics = true; bool PPUView_invertTheMask = false; int PPUView_sprite16Mode = 0; -static uint8 palcache[36] = { 0xFF }; //palette cache +static uint8 pallast[32+3] = { 0 }; // palette cache for change comparison +static uint8 palcache[36] = { 0 }; //palette cache for drawing uint8 chrcache0[0x1000], chrcache1[0x1000], logcache0[0x1000], logcache1[0x1000]; //cache CHR, fixes a refresh problem when right-clicking uint8 *pattern0, *pattern1; //pattern table bitmap arrays uint8 *ppuv_palette; @@ -177,18 +179,17 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) } // update palette only if required - if (memcmp(palcache, PALRAM, 32) != 0) + if ((memcmp(pallast, PALRAM, 32) != 0) || (memcmp(pallast+32, UPALRAM, 3) != 0)) { - // bbit note: let para know that this if is useless and - // will not work because of the lines below that change - // palcache which will make it not equal next time + memcpy(pallast, PALRAM, 32); + memcpy(pallast+32, UPALRAM, 3); // cache palette content memcpy(palcache,PALRAM,32); palcache[0x10] = palcache[0x00]; - palcache[0x14] = palcache[0x00]; - palcache[0x18] = palcache[0x00]; - palcache[0x1C] = palcache[0x00]; + palcache[0x04] = palcache[0x14] = UPALRAM[0]; + palcache[0x08] = palcache[0x18] = UPALRAM[1]; + palcache[0x0C] = palcache[0x1C] = UPALRAM[2]; //draw palettes for (y = 0; y < PALETTEHEIGHT; y++) @@ -220,7 +221,6 @@ void FCEUD_UpdatePPUView(int scanline, int refreshchr) } pbitmap += ((32*4*3)-6); } - memcpy(palcache,PALRAM,32); //palcache which will make it not equal next time } DrawPatternTable(pattern0,chrcache0,logcache0,pindex0); @@ -428,7 +428,8 @@ INT_PTR CALLBACK PPUViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa PPUViewSkip=100; //clear cache - memset(palcache,0,32); + memset(pallast,0,32+3); + memset(palcache,0,36); memset(chrcache0,0,0x1000); memset(chrcache1,0,0x1000); memset(logcache0,0,0x1000); @@ -537,7 +538,6 @@ INT_PTR CALLBACK PPUViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa mouse_x = (mouse_x - paletteDestX) / 32; mouse_y = (mouse_y - paletteDestY) / 32; int ix = (mouse_y<<4)|mouse_x; - if ((ix & 0x10) && !(ix & 0x03)) ix = 0; // palcache 0x10/14/18/1C is bogus $00 values sprintf(str,"Palette: $%02X",palcache[ix]); SetDlgItemText(hwndDlg,LBL_PPUVIEW_TILE1,"Tile:"); SetDlgItemText(hwndDlg,LBL_PPUVIEW_TILE2,"Tile:"); diff --git a/src/ppu.cpp b/src/ppu.cpp index 1e56098c..5aa5aee3 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -2198,7 +2198,7 @@ int FCEUX_PPU_Loop(int skip) { { pixel = addr & 0x1F; } - pixelcolor = PALRAM[pixel]; + pixelcolor = READPAL_MOTHEROFALL(pixel); } //generate the BG data From fbabd180ebf4c1a42e544a9bd7628ec00d20951c Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Sun, 10 Nov 2019 21:10:40 -0500 Subject: [PATCH 03/15] restore symbolic addresses for debugger some of the debugger addresses should not be filtered, as strings can be used like NMI, RST, IRQ, LOAD, INIT, PLAY, NMI1, NMI2, NMI3 --- src/drivers/win/debugger.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/drivers/win/debugger.cpp b/src/drivers/win/debugger.cpp index 3da1c0da..1357c3d8 100644 --- a/src/drivers/win/debugger.cpp +++ b/src/drivers/win/debugger.cpp @@ -279,8 +279,9 @@ INT_PTR CALLBACK AddbpCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara SendDlgItemMessage(hwndDlg, IDC_ADDBP_ADDR_START, EM_SETLIMITTEXT, 4, 0); SendDlgItemMessage(hwndDlg, IDC_ADDBP_ADDR_END, EM_SETLIMITTEXT, 4, 0); - DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_START), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_END), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); + // Don't limit address entry. See: debugcpp offsetStringToInt + //DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_START), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); + //SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_ADDBP_ADDR_END), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); if (WP_edit >= 0) { @@ -1825,12 +1826,14 @@ INT_PTR CALLBACK DebuggerCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_SPR,EM_SETLIMITTEXT,2,0); // limit input - DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PCSEEK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); + // Don't limit address entry. See: debugcpp offsetStringToInt + DefaultEditCtrlProc = (WNDPROC) + //DefaultEditCtrlProc = (WNDPROC)SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PCSEEK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_PC), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_A), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_X), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_VAL_Y), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); - SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_BOOKMARK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); + //SetWindowLongPtr(GetDlgItem(hwndDlg, IDC_DEBUGGER_BOOKMARK), GWLP_WNDPROC, (LONG_PTR)FilterEditCtrlProc); //I'm lazy, disable the controls which I can't mess with right now SendDlgItemMessage(hwndDlg,IDC_DEBUGGER_VAL_PPU,EM_SETREADONLY,TRUE,0); From 88d7f392a98bcba02116ca34e25c83da07608de4 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Fri, 22 Nov 2019 23:22:08 -0500 Subject: [PATCH 04/15] MMC5 arbitrary WRAM size support via iNES 2 (#84) --- src/boards/mmc5.cpp | 69 ++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/src/boards/mmc5.cpp b/src/boards/mmc5.cpp index b2e4cd17..6fa9a243 100644 --- a/src/boards/mmc5.cpp +++ b/src/boards/mmc5.cpp @@ -100,8 +100,9 @@ static uint8 *WRAM = NULL; static uint8 *MMC5fill = NULL; static uint8 *ExRAM = NULL; +const int MMC5WRAMMAX = 1<<7; // 7 bits in register interface (real MMC5 has only 4 pins, however) static uint8 MMC5WRAMsize; //configuration, not state -static uint8 MMC5WRAMIndex[8]; //configuration, not state +static uint8 MMC5WRAMIndex[MMC5WRAMMAX]; //configuration, not state static uint8 MMC5ROMWrProtect[4]; static uint8 MMC5MemIn[5]; @@ -314,6 +315,8 @@ int DetectMMC5WRAMSize(uint32 crc32) { } static void BuildWRAMSizeTable(void) { + bool other = false; // non-standard configuration + // fill first 8 entries int x; for (x = 0; x < 8; x++) { switch (MMC5WRAMsize) { @@ -321,9 +324,22 @@ static void BuildWRAMSizeTable(void) { case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; //0,0,0,0,X,X,X,X case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1 case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X - case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7 + case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7 + default: MMC5WRAMIndex[x] = x; other = true; break; //0,1,2... } } + // extend to fill complete table + if (other) + { + for (x = 0; x < MMC5WRAMMAX && x < MMC5WRAMsize; ++x) MMC5WRAMIndex[x] = x; // linear mapping + for (x = MMC5WRAMsize; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x-MMC5WRAMsize]; // repeat to fill table + // theoretically the table fill should decompose into powers of two for possible mismatched SRAM combos, + // but I don't want to complicate the code with unnecessary hypotheticals + } + else + { + for (x = 8; x < MMC5WRAMMAX; ++x) MMC5WRAMIndex[x] = MMC5WRAMIndex[x & 7]; // fill table, repeating groups of 8 + } } static void MMC5CHRA(void) { @@ -391,7 +407,7 @@ static void MMC5CHRB(void) { } static void MMC5WRAM(uint32 A, uint32 V) { - V = MMC5WRAMIndex[V & 7]; + V = MMC5WRAMIndex[V & (MMC5WRAMMAX-1)]; if (V != 255) { setprg8r(0x10, A, V); FCEU_CheatAddRAM(8, 0x6000, (WRAM + ((V * 8192) & (WRAMSIZE - 1)))); @@ -416,8 +432,8 @@ static void MMC5PRG(void) { MMC5MemIn[1] = MMC5MemIn[2] = 1; } else { MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; - MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); - MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); + MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE); + MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1); } MMC5MemIn[3] = MMC5MemIn[4] = 1; MMC5ROMWrProtect[2] = MMC5ROMWrProtect[3] = 1; @@ -430,8 +446,8 @@ static void MMC5PRG(void) { setprg16(0x8000, (PRGBanks[1] & 0x7F) >> 1); } else { MMC5ROMWrProtect[0] = MMC5ROMWrProtect[1] = 0; - MMC5WRAM(0x8000, PRGBanks[1] & 7 & 0xFE); - MMC5WRAM(0xA000, (PRGBanks[1] & 7 & 0xFE) + 1); + MMC5WRAM(0x8000, PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE); + MMC5WRAM(0xA000, (PRGBanks[1] & (MMC5WRAMMAX-1) & 0xFE) + 1); } if (PRGBanks[2] & 0x80) { MMC5ROMWrProtect[2] = 1; @@ -439,7 +455,7 @@ static void MMC5PRG(void) { setprg8(0xC000, PRGBanks[2] & 0x7F); } else { MMC5ROMWrProtect[2] = 0; - MMC5WRAM(0xC000, PRGBanks[2] & 7); + MMC5WRAM(0xC000, PRGBanks[2] & (MMC5WRAMMAX-1)); } MMC5MemIn[4] = 1; MMC5ROMWrProtect[3] = 1; @@ -453,7 +469,7 @@ static void MMC5PRG(void) { MMC5MemIn[1 + x] = 1; } else { MMC5ROMWrProtect[x] = 0; - MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & 7); + MMC5WRAM(0x8000 + (x << 13), PRGBanks[x] & (MMC5WRAMMAX-1)); } MMC5MemIn[4] = 1; MMC5ROMWrProtect[3] = 1; @@ -516,7 +532,7 @@ static DECLFW(Mapper5_write) { break; case 0x5113: WRAMPage = V; - MMC5WRAM(0x6000, V & 7); + MMC5WRAM(0x6000, V & (MMC5WRAMMAX-1)); break; case 0x5114: case 0x5115: @@ -612,7 +628,7 @@ void MMC5Synco(void) { case 3: PPUNTARAM &= ~(1 << x); vnapage[x] = MMC5fill; break; } } - MMC5WRAM(0x6000, WRAMPage & 7); + MMC5WRAM(0x6000, WRAMPage & (MMC5WRAMMAX-1)); if (!mmc5ABMode) { MMC5CHRB(); MMC5CHRA(); @@ -984,15 +1000,21 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) { if (battery) { info->SaveGame[0] = WRAM; - - //this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you - //I added 64KB for the new 64KB homebrews - if (wsize <= 16) - info->SaveGameLen[0] = 8192; - else if(wsize == 64) - info->SaveGameLen[0] = 64*1024; + if (info->ines2) + { + info->SaveGameLen[0] = info->battery_wram_size; + } else - info->SaveGameLen[0] = 32768; + { + //this is more complex than it looks because it MUST BE, I guess. is there an assumption that only 8KB of 16KB is battery backed? That's NES mappers for you + //I added 64KB for the new 64KB homebrews + if (wsize <= 16) + info->SaveGameLen[0] = 8192; + else if(wsize == 64) + info->SaveGameLen[0] = 64*1024; + else + info->SaveGameLen[0] = 32768; + } } MMC5HackVROMMask = CHRmask4[0]; @@ -1008,7 +1030,14 @@ static void GenMMC5_Init(CartInfo *info, int wsize, int battery) { } void Mapper5_Init(CartInfo *info) { - WRAMSIZE = DetectMMC5WRAMSize(info->CRC32); + if (info->ines2) + { + WRAMSIZE = (info->wram_size + info->battery_wram_size) / 1024; + } + else + { + WRAMSIZE = DetectMMC5WRAMSize(info->CRC32); + } GenMMC5_Init(info, WRAMSIZE, info->battery); } From ed4f5d0000e17b6ae88c4e93e2f9e0695dbceac0 Mon Sep 17 00:00:00 2001 From: Andypro1 <871829+Andypro1@users.noreply.github.com> Date: Fri, 22 Nov 2019 23:29:25 -0500 Subject: [PATCH 05/15] Moved lua memory_writebyte() to legacymemory_writebyte() and changed the memory_writebyte() implementation to avoid the legacy cheat engine code. (#67) --- src/lua-engine.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index 563452ae..6e65f6c5 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -1416,6 +1416,16 @@ static int memory_readwordsigned(lua_State *L) { } static int memory_writebyte(lua_State *L) { + uint32 A = luaL_checkinteger(L, 1); + uint8 V = luaL_checkinteger(L, 2); + + if(A < 0x10000) + BWrite[A](A, V); + + return 0; +} + +static int legacymemory_writebyte(lua_State *L) { FCEU_CheatSetByte(luaL_checkinteger(L,1), luaL_checkinteger(L,2)); return 0; } @@ -5764,6 +5774,7 @@ static const struct luaL_reg memorylib [] = { {"readwordsigned", memory_readwordsigned}, {"readwordunsigned", memory_readword}, // alternate naming scheme for unsigned {"writebyte", memory_writebyte}, + {"legacywritebyte", legacymemory_writebyte}, {"getregister", memory_getregister}, {"setregister", memory_setregister}, From 749567adf690cf331fc296b760cb64f4f6c58925 Mon Sep 17 00:00:00 2001 From: Aleksandr Charkov Date: Fri, 6 Dec 2019 00:27:01 +0200 Subject: [PATCH 06/15] fix mispell (#86) deprecated --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index a1350938..d906928f 100644 --- a/README +++ b/README @@ -65,7 +65,7 @@ tweak some of these options. 4 - GUI ------- You can enable the GTK GUI by setting GTK to 1 in the SConstruct build file. -GfceuX is deprecatiated in favor of the new GTK GUI. You can disable the GTK GUI at +GfceuX is deprecated in favor of the new GTK GUI. You can disable the GTK GUI at run-time by passing the --nogui option, or disable it at build-time by setting GTK to 0 in the SConstruct file. If you prefer GTK3 to GTK2, you can set the GTK3 BoolVariable to 1 in the SConstruct. From 0b4be4b639371204642f22def7bd92ea18a4c2f3 Mon Sep 17 00:00:00 2001 From: dinkc64 Date: Mon, 16 Dec 2019 00:45:10 -0500 Subject: [PATCH 07/15] fds.cpp: new fds image handling, fixes saving issues with some games (Bubble Bobble, Super Lode Runner II, ...) --- src/fds.cpp | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/src/fds.cpp b/src/fds.cpp index 463ba327..e0aa9a84 100644 --- a/src/fds.cpp +++ b/src/fds.cpp @@ -86,6 +86,20 @@ static int32 DiskPtr; static int32 DiskSeekIRQ; static uint8 SelectDisk, InDisk; +/* 4024(w), 4025(w), 4031(r) by dink(fbneo) */ +#define USE_DINK // remove this and old code after testing phase +enum FDS_DiskBlockIDs { DSK_INIT = 0, DSK_VOLUME, DSK_FILECNT, DSK_FILEHDR, DSK_FILEDATA }; +static uint8 mapperFDS_control; // 4025(w) control register +static uint16 mapperFDS_filesize; // size of file being read/written +static uint8 mapperFDS_block; // block-id of current block +static uint16 mapperFDS_blockstart; // start-address of current block +static uint16 mapperFDS_blocklen; // length of current block +static uint16 mapperFDS_diskaddr; // current address relative to blockstart +static uint8 mapperFDS_diskaccess; // disk needs to be accessed at least once before writing +#define fds_disk() (diskdata[InDisk][mapperFDS_blockstart + mapperFDS_diskaddr]) +#define mapperFDS_diskinsert (InDisk != 255) + + #define DC_INC 1 void FDSGI(GI h) { @@ -141,6 +155,16 @@ static void FDSInit(void) { FDSSoundReset(); InDisk = 0; SelectDisk = 0; + +#ifdef USE_DINK + mapperFDS_control = 0; + mapperFDS_filesize = 0; + mapperFDS_block = 0; + mapperFDS_blockstart = 0; + mapperFDS_blocklen = 0; + mapperFDS_diskaddr = 0; + mapperFDS_diskaccess = 0; +#endif } void FCEU_FDSInsert(void) @@ -232,6 +256,7 @@ static DECLFR(FDSRead4030) { return ret; } +#ifndef USE_DINK static DECLFR(FDSRead4031) { static uint8 z = 0; if (InDisk != 255) { @@ -244,6 +269,51 @@ static DECLFR(FDSRead4031) { } return z; } + +#else + +static DECLFR(FDSRead4031) { + static uint8 ret = 0; + + ret = 0xff; + if (mapperFDS_diskinsert && mapperFDS_control & 0x04) { + mapperFDS_diskaccess = 1; + + ret = 0; + + switch (mapperFDS_block) { + case DSK_FILEHDR: + if (mapperFDS_diskaddr < mapperFDS_blocklen) { + ret = fds_disk(); + switch (mapperFDS_diskaddr) { + case 13: mapperFDS_filesize = ret; break; + case 14: + mapperFDS_filesize |= ret << 8; + //char fdsfile[10]; + //strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8); + //printf("Read file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize); + break; + } + mapperFDS_diskaddr++; + } + break; + default: + if (mapperFDS_diskaddr < mapperFDS_blocklen) { + ret = fds_disk(); + mapperFDS_diskaddr++; + } + break; + } + + DiskSeekIRQ = 150; + X6502_IRQEnd(FCEU_IQEXT2); + } + + return ret; +} + +#endif + static DECLFR(FDSRead4032) { uint8 ret; @@ -533,6 +603,7 @@ static DECLFW(FDSWrite) { break; case 0x4023: break; case 0x4024: +#ifndef USE_DINK if ((InDisk != 255) && !(FDSRegs[5] & 0x4) && (FDSRegs[3] & 0x1)) { if (DiskPtr >= 0 && DiskPtr < 65500) { if (writeskip) @@ -543,8 +614,43 @@ static DECLFW(FDSWrite) { } } } +#else + if (mapperFDS_diskinsert && ~mapperFDS_control & 0x04) { + + if (mapperFDS_diskaccess == 0) { + mapperFDS_diskaccess = 1; + break; + } + + switch (mapperFDS_block) { + case DSK_FILEHDR: + if (mapperFDS_diskaddr < mapperFDS_blocklen) { + fds_disk() = V; + switch (mapperFDS_diskaddr) { + case 13: mapperFDS_filesize = V; break; + case 14: + mapperFDS_filesize |= V << 8; + //char fdsfile[10]; + //strncpy(fdsfile, (char*)&diskdata[InDisk][mapperFDS_blockstart + 3], 8); + //printf("Write file: %s (size: %d)\n"), fdsfile, mapperFDS_filesize); + break; + } + mapperFDS_diskaddr++; + } + break; + default: + if (mapperFDS_diskaddr < mapperFDS_blocklen) { + fds_disk() = V; + mapperFDS_diskaddr++; + } + break; + } + + } +#endif break; case 0x4025: +#ifndef USE_DINK X6502_IRQEnd(FCEU_IQEXT2); if (InDisk != 255) { if (!(V & 0x40)) { @@ -561,6 +667,54 @@ static DECLFW(FDSWrite) { if (V & 0x40) DiskSeekIRQ = 200; } setmirror(((V >> 3) & 1) ^ 1); +#else + X6502_IRQEnd(FCEU_IQEXT2); + if (mapperFDS_diskinsert) { + if (V & 0x40 && ~mapperFDS_control & 0x40) { + mapperFDS_diskaccess = 0; + + DiskSeekIRQ = 150; + + // blockstart - address of block on disk + // diskaddr - address relative to blockstart + // _block -> _blockID ? + mapperFDS_blockstart += mapperFDS_diskaddr; + mapperFDS_diskaddr = 0; + + mapperFDS_block++; + if (mapperFDS_block > DSK_FILEDATA) + mapperFDS_block = DSK_FILEHDR; + + switch (mapperFDS_block) { + case DSK_VOLUME: + mapperFDS_blocklen = 0x38; + break; + case DSK_FILECNT: + mapperFDS_blocklen = 0x02; + break; + case DSK_FILEHDR: + mapperFDS_blocklen = 0x10; + break; + case DSK_FILEDATA: // + mapperFDS_blocklen = 0x01 + mapperFDS_filesize; + break; + } + } + + if (V & 0x02) { // transfer reset + mapperFDS_block = DSK_INIT; + mapperFDS_blockstart = 0; + mapperFDS_blocklen = 0; + mapperFDS_diskaddr = 0; + DiskSeekIRQ = 150; + } + if (V & 0x40) { // turn on motor + DiskSeekIRQ = 150; + } + } + mapperFDS_control = V; + setmirror(((V >> 3) & 1) ^ 1); +#endif break; } FDSRegs[A & 7] = V; @@ -749,6 +903,15 @@ int FDSLoad(const char *name, FCEUFILE *fp) { AddExState(&SelectDisk, 1, 0, "SELD"); AddExState(&InDisk, 1, 0, "INDI"); AddExState(&DiskWritten, 1, 0, "DSKW"); +#ifdef USE_DINK + AddExState(&mapperFDS_control, 1, 0, "CTRG"); + AddExState(&mapperFDS_filesize, 2, 1, "FLSZ"); + AddExState(&mapperFDS_block, 1, 0, "BLCK"); + AddExState(&mapperFDS_blockstart, 2, 1, "BLKS"); + AddExState(&mapperFDS_blocklen, 2, 1, "BLKL"); + AddExState(&mapperFDS_diskaddr, 2, 1, "DADR"); + AddExState(&mapperFDS_diskaccess, 1, 0, "DACC"); +#endif CHRRAMSize = 8192; CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); From 6abfe09caff3d354b70927951207ec6f41d03f59 Mon Sep 17 00:00:00 2001 From: g0me3 Date: Sat, 4 Jan 2020 13:16:54 +0300 Subject: [PATCH 08/15] Famicom Network System controller added misc fixes to mappers --- src/boards/addrlatch.cpp | 9 ++----- src/boards/unrom512.cpp | 46 +++++++++++++++++------------------ src/drivers/win/input.cpp | 27 ++++++++++++++++++++ src/git.h | 6 +++-- src/ines.cpp | 3 ++- src/input.cpp | 4 +++ vc/vc14_fceux.vcxproj | 1 + vc/vc14_fceux.vcxproj.filters | 3 +++ 8 files changed, 66 insertions(+), 33 deletions(-) diff --git a/src/boards/addrlatch.cpp b/src/boards/addrlatch.cpp index 7633bce8..05d05f0b 100644 --- a/src/boards/addrlatch.cpp +++ b/src/boards/addrlatch.cpp @@ -237,13 +237,8 @@ void Mapper200_Init(CartInfo *info) { //------------------ Map 201 --------------------------- static void M201Sync(void) { - if (latche & 8) { - setprg32(0x8000, latche & 3); - setchr8(latche & 3); - } else { - setprg32(0x8000, 0); - setchr8(0); - } + setprg32(0x8000, latche & 3); + setchr8(latche & 3); } void Mapper201_Init(CartInfo *info) { diff --git a/src/boards/unrom512.cpp b/src/boards/unrom512.cpp index ac6bd57b..845b9689 100644 --- a/src/boards/unrom512.cpp +++ b/src/boards/unrom512.cpp @@ -47,31 +47,31 @@ static uint8 flash_save=0, flash_state=0, flash_mode=0, flash_bank; static void (*WLSync)(void); static void (*WHSync)(void); -static INLINE void setfpageptr(int s, uint32 A, uint8 *p) { - uint32 AB = A >> 11; - int x; - - if (p) - for (x = (s >> 1) - 1; x >= 0; x--) { - FlashPage[AB + x] = p - A; - } - else - for (x = (s >> 1) - 1; x >= 0; x--) { - FlashPage[AB + x] = 0; - } +static INLINE void setfpageptr(int s, uint32 A, uint8 *p) { + uint32 AB = A >> 11; + int x; + + if (p) + for (x = (s >> 1) - 1; x >= 0; x--) { + FlashPage[AB + x] = p - A; + } + else + for (x = (s >> 1) - 1; x >= 0; x--) { + FlashPage[AB + x] = 0; + } } -void setfprg16(uint32 A, uint32 V) { - if (PRGsize[0] >= 16384) { - V &= PRGmask16[0]; - setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0); - } else { - uint32 VA = V << 3; - int x; - - for (x = 0; x < 8; x++) - setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0); - } +void setfprg16(uint32 A, uint32 V) { + if (PRGsize[0] >= 16384) { + V &= PRGmask16[0]; + setfpageptr(16, A, flashdata ? (&flashdata[V << 14]) : 0); + } else { + uint32 VA = V << 3; + int x; + + for (x = 0; x < 8; x++) + setfpageptr(2, A + (x << 11), flashdata ? (&flashdata[((VA + x) & PRGmask2[0]) << 11]) : 0); + } } void inc_flash_write_count(uint8 bank, uint32 A) diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index 4b1165a7..0eb9e32f 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -93,6 +93,7 @@ static uint8 HyperShotData=0; static uint32 MahjongData=0; static uint32 FTrainerData=0; static uint8 TopRiderData=0; +static uint32 FamiNetSysData = 0; static uint8 BWorldData[1+13+1]; @@ -104,6 +105,7 @@ static void UpdateHyperShot(void); static void UpdateMahjong(void); static void UpdateFTrainer(void); static void UpdateTopRider(void); +static void UpdateFamiNetSys(void); static uint32 snespad_return[4]; static uint32 JSreturn=0; @@ -463,6 +465,7 @@ void FCEUD_UpdateInput() case SIFC_FTRAINERB: case SIFC_FTRAINERA: UpdateFTrainer();break; case SIFC_TOPRIDER: UpdateTopRider();break; + case SIFC_FAMINETSYS: UpdateFamiNetSys(); break; case SIFC_OEKAKIDS: mouse=true; break; } @@ -566,6 +569,9 @@ void InitInputPorts(bool fourscore) case SIFC_TOPRIDER: InputDPtr=&TopRiderData; break; + case SIFC_FAMINETSYS: + InputDPtr = &FamiNetSysData; + break; case SIFC_BWORLD: InputDPtr=BWorldData; break; @@ -718,6 +724,27 @@ static void UpdateTopRider(void) TopRiderData|=1<= SIFC_NONE && esifc <= SIFC_COUNT) diff --git a/src/ines.cpp b/src/ines.cpp index 97e28f6b..5111f481 100644 --- a/src/ines.cpp +++ b/src/ines.cpp @@ -211,6 +211,7 @@ static void SetInput(void) { {0xb8b9aca3, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman {0x5112dc21, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman {0xaf4010ea, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // World Class Track Meet + {0x67b126b9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FAMINETSYS }, // Famicom Network System {0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET } }; int x = 0; @@ -724,7 +725,7 @@ BMAPPINGLocal bmap[] = { {"F-15 MMC3 Based", 259, BMCF15_Init}, {"HP10xx/H20xx Boards", 260, BMCHPxx_Init}, {"810544-CA-1", 261, BMC810544CA1_Init}, - { "KONAMI QTAi Board", 547, QTAi_Init }, + {"KONAMI QTAi Board", 547, QTAi_Init }, {"", 0, NULL} }; diff --git a/src/input.cpp b/src/input.cpp index 5f840fff..ff2f6d76 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -77,6 +77,7 @@ extern INPUTCFC *FCEU_InitFamilyTrainerA(void); extern INPUTCFC *FCEU_InitFamilyTrainerB(void); extern INPUTCFC *FCEU_InitOekaKids(void); extern INPUTCFC *FCEU_InitTopRider(void); +extern INPUTCFC *FCEU_InitFamiNetSys(void); extern INPUTCFC *FCEU_InitBarcodeWorld(void); //--------------- @@ -534,6 +535,9 @@ static void SetInputStuffFC() case SIFC_TOPRIDER: portFC.driver=FCEU_InitTopRider(); break; + case SIFC_FAMINETSYS: + portFC.driver = FCEU_InitFamiNetSys(); + break; } } diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj index 2e3bb96d..882648de 100644 --- a/vc/vc14_fceux.vcxproj +++ b/vc/vc14_fceux.vcxproj @@ -688,6 +688,7 @@ + diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters index 221a661b..3b4f039f 100644 --- a/vc/vc14_fceux.vcxproj.filters +++ b/vc/vc14_fceux.vcxproj.filters @@ -1096,6 +1096,9 @@ drivers\win + + input + From e43fe75b67966126b9368e32056f30a17f48756a Mon Sep 17 00:00:00 2001 From: g0me3 Date: Sat, 4 Jan 2020 13:48:32 +0300 Subject: [PATCH 09/15] forgot to upload file --- .gitignore | 4 ++++ src/input/fns.cpp | 59 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/input/fns.cpp diff --git a/.gitignore b/.gitignore index fdbc73fa..070ae89b 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,7 @@ fceux-net-server .sconsign.dblite .deps .dirstamp +/output/movies +/output/cheats +/output/snaps +/output/sav diff --git a/src/input/fns.cpp b/src/input/fns.cpp new file mode 100644 index 00000000..dcca51c0 --- /dev/null +++ b/src/input/fns.cpp @@ -0,0 +1,59 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2019 CaH4e3 + * + * 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 + * + * Family Network System controller + * + */ + +#include +#include "share.h" + +static int readbit; +static int32 readdata; + +static uint8 Read(int w, uint8 ret) +{ + if (!w) + { + if (readbit < 24) { + ret |= ((readdata >> readbit) & 1) << 1; + readbit++; + } else + ret |= 2; // sense! + } + return ret; +} + +static void Strobe(void) +{ + readbit = 0; +} + +static void Update(void *data, int arg) +{ + readdata = *(uint32*)data; +} + +static INPUTCFC FamiNetSys = { Read, 0, Strobe, Update, 0, 0 }; + +INPUTCFC *FCEU_InitFamiNetSys(void) +{ + return(&FamiNetSys); +} + From db003f841d8d1f512e80194d0d3b6bf7b456fb77 Mon Sep 17 00:00:00 2001 From: g0me3 Date: Sun, 12 Jan 2020 16:56:37 +0300 Subject: [PATCH 10/15] fixed #90 (debug breakpoint missing if conditions used) --- src/debug.cpp | 61 ++++++++++++++++++++++++++------------------------- src/debug.h | 2 +- src/ppu.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- src/unif.h | 2 +- 4 files changed, 91 insertions(+), 33 deletions(-) diff --git a/src/debug.cpp b/src/debug.cpp index dbde6a31..3a1e2d2c 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -533,35 +533,36 @@ void IncrementInstructionsCounters() delta_instructions++; } -void BreakHit(int bp_num, bool force) -{ - if(!force) +bool CondForbidTest(int bp_num) { + if (bp_num >= 0 && !condition(&watchpoint[bp_num])) { - if (bp_num >= 0 && !condition(&watchpoint[bp_num])) - { - return; // condition rejected - } + return false; // condition rejected + } - //check to see whether we fall in any forbid zone - for (int i = 0; i < numWPs; i++) - { - watchpointinfo& wp = watchpoint[i]; - if(!(wp.flags & WP_F) || !(wp.flags & WP_E)) - continue; + //check to see whether we fall in any forbid zone + for (int i = 0; i < numWPs; i++) + { + watchpointinfo& wp = watchpoint[i]; + if (!(wp.flags & WP_F) || !(wp.flags & WP_E)) + continue; - if (condition(&wp)) - { - if (wp.endaddress) { - if( (wp.address <= _PC) && (wp.endaddress >= _PC) ) - return; //forbid - } else { - if(wp.address == _PC) - return; //forbid - } + if (condition(&wp)) + { + if (wp.endaddress) { + if ((wp.address <= _PC) && (wp.endaddress >= _PC)) + return false; //forbid + } + else { + if (wp.address == _PC) + return false; //forbid } } } + return true; +} +void BreakHit(int bp_num) +{ FCEUI_SetEmulationPaused(EMULATIONPAUSED_PAUSED); //mbg merge 7/19/06 changed to use EmulationPaused() #ifdef WIN32 @@ -585,17 +586,17 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) { if (break_asap) { break_asap = false; - BreakHit(BREAK_TYPE_LUA, true); + BreakHit(BREAK_TYPE_LUA); } if (break_on_cycles && ((timestampbase + (uint64)timestamp - total_cycles_base) > break_cycles_limit)) - BreakHit(BREAK_TYPE_CYCLES_EXCEED, true); + BreakHit(BREAK_TYPE_CYCLES_EXCEED); if (break_on_instructions && (total_instructions > break_instructions_limit)) - BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED, true); + BreakHit(BREAK_TYPE_INSTRUCTIONS_EXCEED); //if the current instruction is bad, and we are breaking on bad opcodes, then hit the breakpoint if(dbgstate.badopbreak && (size == 0)) - BreakHit(BREAK_TYPE_BADOP, true); + BreakHit(BREAK_TYPE_BADOP); //if we're stepping out, track the nest level if (dbgstate.stepout) { @@ -614,7 +615,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) { //if we're stepping, then we'll always want to break if (dbgstate.step) { dbgstate.step = false; - BreakHit(BREAK_TYPE_STEP, true); + BreakHit(BREAK_TYPE_STEP); return; } @@ -626,7 +627,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) { if (diff<=0) { dbgstate.runline=false; - BreakHit(BREAK_TYPE_STEP, true); + BreakHit(BREAK_TYPE_STEP); return; } } @@ -635,7 +636,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) { if ((watchpoint[64].address == _PC) && (watchpoint[64].flags)) { watchpoint[64].address = 0; watchpoint[64].flags = 0; - BreakHit(BREAK_TYPE_STEP, true); + BreakHit(BREAK_TYPE_STEP); return; } @@ -657,7 +658,7 @@ static void breakpoint(uint8 *opcode, uint16 A, int size) { default: break; } - #define BREAKHIT(x) { breakHit = (x); goto STOPCHECKING; } +#define BREAKHIT(x) { if (CondForbidTest(x)) { breakHit = (x); goto STOPCHECKING; } } int breakHit = -1; for (i = 0; i < numWPs; i++) { diff --git a/src/debug.h b/src/debug.h index 9c25b376..5cf883c0 100644 --- a/src/debug.h +++ b/src/debug.h @@ -93,7 +93,7 @@ static INLINE int FCEUI_GetLoggingCD() { return debug_loggingCD; } extern int iaPC; extern uint32 iapoffset; //mbg merge 7/18/06 changed from int void DebugCycle(); -void BreakHit(int bp_num, bool force = false); +void BreakHit(int bp_num); extern bool break_asap; extern uint64 total_cycles_base; diff --git a/src/ppu.cpp b/src/ppu.cpp index 5aa5aee3..3d3c9656 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -1218,7 +1218,64 @@ static void RefreshLine(int lastpixel) { #undef PPU_VRC5FETCH } else { for (X1 = firsttile; X1 < lasttile; X1++) { - #include "pputile.inc" +// #include "pputile.inc" + uint8 *C; + register uint8 cc; + uint32 vadr; + + register uint8 zz; + + if (X1 >= 2) { + uint8 *S = PALRAM; + uint32 pixdata; + + pixdata = ppulut1[(pshift[0] >> (8 - XOffset)) & 0xFF] | ppulut2[(pshift[1] >> (8 - XOffset)) & 0xFF]; + + pixdata |= ppulut3[XOffset | (atlatch << 3)]; + + P[0] = S[pixdata & 0xF]; + pixdata >>= 4; + P[1] = S[pixdata & 0xF]; + pixdata >>= 4; + P[2] = S[pixdata & 0xF]; + pixdata >>= 4; + P[3] = S[pixdata & 0xF]; + pixdata >>= 4; + P[4] = S[pixdata & 0xF]; + pixdata >>= 4; + P[5] = S[pixdata & 0xF]; + pixdata >>= 4; + P[6] = S[pixdata & 0xF]; + pixdata >>= 4; + P[7] = S[pixdata & 0xF]; + P += 8; + } + + zz = RefreshAddr & 0x1F; + C = vnapage[(RefreshAddr >> 10) & 3]; + + vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; // Fetch name table byte. + cc = C[0x3c0 + (zz >> 2) + ((RefreshAddr & 0x380) >> 4)]; // Fetch attribute table byte. + cc = ((cc >> ((zz & 2) + ((RefreshAddr & 0x40) >> 4))) & 3); + + atlatch >>= 2; + atlatch |= cc << 2; + + pshift[0] <<= 8; + pshift[1] <<= 8; + + C = VRAMADR(vadr); + if (ScreenON) + RENDER_LOGP(C); + pshift[0] |= C[0]; + if (ScreenON) + RENDER_LOGP(C + 8); + pshift[1] |= C[8]; + + if ((RefreshAddr & 0x1f) == 0x1f) + RefreshAddr ^= 0x41F; + else + RefreshAddr++; } } } diff --git a/src/unif.h b/src/unif.h index f85e6e45..94d5db83 100644 --- a/src/unif.h +++ b/src/unif.h @@ -51,7 +51,7 @@ void EKROM_Init(CartInfo *info); void ELROM_Init(CartInfo *info); void ETROM_Init(CartInfo *info); void EWROM_Init(CartInfo *info); -void GNROM_Init(CartInfo *info); +//void GNROM_Init(CartInfo *info); void HKROM_Init(CartInfo *info); void LE05_Init(CartInfo *info); void LH10_Init(CartInfo *info); From 4fe5da841c238ac48ca53119279c712f33a1990b Mon Sep 17 00:00:00 2001 From: g0me3 Date: Sun, 12 Jan 2020 17:07:23 +0300 Subject: [PATCH 11/15] forgot to remove debug code --- src/debug.h | 1 + src/ppu.cpp | 59 +---------------------------------------------------- 2 files changed, 2 insertions(+), 58 deletions(-) diff --git a/src/debug.h b/src/debug.h index 5cf883c0..ef21f4c1 100644 --- a/src/debug.h +++ b/src/debug.h @@ -93,6 +93,7 @@ static INLINE int FCEUI_GetLoggingCD() { return debug_loggingCD; } extern int iaPC; extern uint32 iapoffset; //mbg merge 7/18/06 changed from int void DebugCycle(); +bool CondForbidTest(int bp_num); void BreakHit(int bp_num); extern bool break_asap; diff --git a/src/ppu.cpp b/src/ppu.cpp index 3d3c9656..5aa5aee3 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -1218,64 +1218,7 @@ static void RefreshLine(int lastpixel) { #undef PPU_VRC5FETCH } else { for (X1 = firsttile; X1 < lasttile; X1++) { -// #include "pputile.inc" - uint8 *C; - register uint8 cc; - uint32 vadr; - - register uint8 zz; - - if (X1 >= 2) { - uint8 *S = PALRAM; - uint32 pixdata; - - pixdata = ppulut1[(pshift[0] >> (8 - XOffset)) & 0xFF] | ppulut2[(pshift[1] >> (8 - XOffset)) & 0xFF]; - - pixdata |= ppulut3[XOffset | (atlatch << 3)]; - - P[0] = S[pixdata & 0xF]; - pixdata >>= 4; - P[1] = S[pixdata & 0xF]; - pixdata >>= 4; - P[2] = S[pixdata & 0xF]; - pixdata >>= 4; - P[3] = S[pixdata & 0xF]; - pixdata >>= 4; - P[4] = S[pixdata & 0xF]; - pixdata >>= 4; - P[5] = S[pixdata & 0xF]; - pixdata >>= 4; - P[6] = S[pixdata & 0xF]; - pixdata >>= 4; - P[7] = S[pixdata & 0xF]; - P += 8; - } - - zz = RefreshAddr & 0x1F; - C = vnapage[(RefreshAddr >> 10) & 3]; - - vadr = (C[RefreshAddr & 0x3ff] << 4) + vofs; // Fetch name table byte. - cc = C[0x3c0 + (zz >> 2) + ((RefreshAddr & 0x380) >> 4)]; // Fetch attribute table byte. - cc = ((cc >> ((zz & 2) + ((RefreshAddr & 0x40) >> 4))) & 3); - - atlatch >>= 2; - atlatch |= cc << 2; - - pshift[0] <<= 8; - pshift[1] <<= 8; - - C = VRAMADR(vadr); - if (ScreenON) - RENDER_LOGP(C); - pshift[0] |= C[0]; - if (ScreenON) - RENDER_LOGP(C + 8); - pshift[1] |= C[8]; - - if ((RefreshAddr & 0x1f) == 0x1f) - RefreshAddr ^= 0x41F; - else - RefreshAddr++; + #include "pputile.inc" } } } From 18165938d45cda62fb0d551a780a3e1299ade899 Mon Sep 17 00:00:00 2001 From: g0me3 Date: Thu, 16 Jan 2020 21:33:37 +0300 Subject: [PATCH 12/15] preliminary, basic hookup of Family Network System base board + MMC1 cassette emulation --- src/boards/fns.cpp | 252 ++++++++++++++++++++++++++++++++++ src/debug.cpp | 6 +- src/unif.cpp | 1 + src/unif.h | 1 + vc/vc14_fceux.vcxproj | 1 + vc/vc14_fceux.vcxproj.filters | 3 + 6 files changed, 261 insertions(+), 3 deletions(-) create mode 100644 src/boards/fns.cpp diff --git a/src/boards/fns.cpp b/src/boards/fns.cpp new file mode 100644 index 00000000..facb3c5e --- /dev/null +++ b/src/boards/fns.cpp @@ -0,0 +1,252 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2020 CaH4e3 + * + * 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 + * + * Famicom Network System Base Unit + MMC1 cartridge board + * + */ + +#include "mapinc.h" + +static uint8 DRegs[4]; +static uint8 Buffer, BufferShift; + +static uint32 WRAMSIZE; +static uint8 *WRAM = NULL; + +static int kanji_pos, kanji_page, r40C0; +static int IRQa, IRQCount; + +static DECLFW(MBWRAM) { + if (!(DRegs[3] & 0x10)) + Page[A >> 11][A] = V; +} + +static DECLFR(MAWRAM) { + if (DRegs[3] & 0x10) + return X.DB; + return(Page[A >> 11][A]); +} + +static void MMC1CHR(void) { + setchr8((r40C0 >> 3) & 1); +} + +static void MMC1PRG(void) { + uint8 offs_16banks = DRegs[1] & 0x10; + uint8 prg_reg = DRegs[3] & 0xF; + setprg8r(0x10, 0x6000, DRegs[1] & 3); + switch (DRegs[0] & 0xC) { + case 0xC: + setprg16(0x8000, (prg_reg + offs_16banks)); + setprg16(0xC000, 0xF + offs_16banks); + break; + case 0x8: + setprg16(0xC000, (prg_reg + offs_16banks)); + setprg16(0x8000, offs_16banks); + break; + case 0x0: + case 0x4: + setprg16(0x8000, ((prg_reg & ~1) + offs_16banks)); + setprg16(0xc000, ((prg_reg & ~1) + offs_16banks + 1)); + break; + } +} + +static void MMC1MIRROR(void) { + switch (DRegs[0] & 3) { + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + } +} + +static uint64 lreset; +static DECLFW(MMC1_write) { + int n = (A >> 13) - 4; + if ((timestampbase + timestamp) < (lreset + 2)) + return; + + if (V & 0x80) { + DRegs[0] |= 0xC; + BufferShift = Buffer = 0; + MMC1PRG(); + lreset = timestampbase + timestamp; + return; + } + + Buffer |= (V & 1) << (BufferShift++); + + if (BufferShift == 5) { + DRegs[n] = Buffer; + // FCEU_printf("MMC1 REG%d:%02x\n", n, Buffer); + BufferShift = Buffer = 0; + switch (n) { + case 0: MMC1MIRROR(); // break; + case 1: // break; +// case 2: MMC1CHR(); break; + case 3: MMC1PRG(); break; + } + } +} + +static void MMC1_Restore(int version) { + MMC1MIRROR(); + MMC1CHR(); + MMC1PRG(); + lreset = 0; +} + +static void MMC1CMReset(void) { + int i; + + for (i = 0; i < 4; i++) + DRegs[i] = 0; + Buffer = BufferShift = 0; + DRegs[0] = 0x1F; + + DRegs[1] = 0; + DRegs[2] = 0; + DRegs[3] = 0; + + MMC1MIRROR(); + MMC1CHR(); + MMC1PRG(); +} + +static DECLFW(FNC_cmd_write) { + switch (A) { + case 0x40A6: { + IRQCount = (IRQCount & 0xFF00) | V; + break; + } + case 0x40A7: { + IRQCount = (IRQCount & 0x00FF) | (V << 8); + break; + } + case 0x40A8: { + IRQa = V; + break; + } + case 0x40B0: { + kanji_page = V & 1; + break; + } + case 0x40C0: { +// FCEU_printf("FNS W %04x:%02x\n", A, V); + r40C0 = V; + MMC1CHR(); + break; + } +// default: +// FCEU_printf("FNS W %04x:%02x\n", A, V); + } +} + +static DECLFR(FNC_stat_read) { + switch (A) { + case 0x40A2: { + int ret = (IRQa >> 1); + X6502_IRQEnd(FCEU_IQEXT); + IRQa = 0; + return ret; + } + case 0x40B0: { + kanji_pos = 0; + return 0; + } + case 0x40C0: { +// FCEU_printf("FNS R %04x\n", A); + int ret = r40C0; + r40C0 &= 0; + return ret; + } + default: { +// FCEU_printf("FNS R %04x\n", A); + return 0xff; + } + } +} + +static DECLFR(FNC_kanji_read) { + int32 ofs = ((A & 0xFFF) << 5) + kanji_pos; + kanji_pos++; + kanji_pos &= 0x1F; +// if (PRGptr[1] != NULL) // iNES debug + return PRGptr[1][ofs]; +// else +// return CHRptr[0][ofs]; +} + +void NFC_IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void FNS_Power(void) { + lreset = 0; + SetWriteHandler(0x8000, 0xFFFF, MMC1_write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + kanji_page = 0; + kanji_pos = 0; + r40C0 = 0xC0; + + SetWriteHandler(0x4080, 0x40FF, FNC_cmd_write); + SetReadHandler(0x4080, 0x40FF, FNC_stat_read); + SetReadHandler(0x5000, 0x5FFF, FNC_kanji_read); + + SetReadHandler(0x6000, 0x7FFF, MAWRAM); + SetWriteHandler(0x6000, 0x7FFF, MBWRAM); + + FCEU_CheatAddRAM(8, 0x6000, WRAM); + MMC1CMReset(); +} + +static void FNS_Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void FNS_Init(CartInfo *info) { + info->Close = FNS_Close; + info->Power = FNS_Power; + + GameStateRestore = MMC1_Restore; + MapIRQHook = NFC_IRQ; + + WRAMSIZE = (8 + 32) * 1024; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + + AddExState(DRegs, 4, 0, "DREG"); + AddExState(&lreset, 8, 1, "LRST"); + AddExState(&Buffer, 1, 1, "BFFR"); + AddExState(&BufferShift, 1, 1, "BFRS"); +} diff --git a/src/debug.cpp b/src/debug.cpp index 3a1e2d2c..04a7cf73 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -536,7 +536,7 @@ void IncrementInstructionsCounters() bool CondForbidTest(int bp_num) { if (bp_num >= 0 && !condition(&watchpoint[bp_num])) { - return false; // condition rejected + return false; // condition rejected } //check to see whether we fall in any forbid zone @@ -550,11 +550,11 @@ bool CondForbidTest(int bp_num) { { if (wp.endaddress) { if ((wp.address <= _PC) && (wp.endaddress >= _PC)) - return false; //forbid + return false; // forbid } else { if (wp.address == _PC) - return false; //forbid + return false; // forbid } } } diff --git a/src/unif.cpp b/src/unif.cpp index 3f8aaafc..8b553a02 100644 --- a/src/unif.cpp +++ b/src/unif.cpp @@ -472,6 +472,7 @@ static BMAPPING bmap[] = { { "80013-B", BMC80013B_Init, 0 }, { "HPxx", BMCHPxx_Init, 0 }, { "MINDKIDS", MINDKIDS_Init, BMCFLAG_256KCHRR }, + { "FNS", FNS_Init, BMCFLAG_16KCHRR }, { 0, 0, 0 } }; diff --git a/src/unif.h b/src/unif.h index 94d5db83..9864a88a 100644 --- a/src/unif.h +++ b/src/unif.h @@ -159,6 +159,7 @@ void BMC8IN1_Init(CartInfo *info); void BMC80013B_Init(CartInfo *info); void BMCHPxx_Init(CartInfo *info); void MINDKIDS_Init(CartInfo *info); +void FNS_Init(CartInfo *info); extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM // bank switcherooing with certain boards... diff --git a/vc/vc14_fceux.vcxproj b/vc/vc14_fceux.vcxproj index 882648de..e0beaac1 100644 --- a/vc/vc14_fceux.vcxproj +++ b/vc/vc14_fceux.vcxproj @@ -458,6 +458,7 @@ + diff --git a/vc/vc14_fceux.vcxproj.filters b/vc/vc14_fceux.vcxproj.filters index 3b4f039f..44320047 100644 --- a/vc/vc14_fceux.vcxproj.filters +++ b/vc/vc14_fceux.vcxproj.filters @@ -1099,6 +1099,9 @@ input + + boards + From fb8d46d9697cb24b0ebe79d84eedf282f69ab337 Mon Sep 17 00:00:00 2001 From: g0me3 Date: Wed, 29 Jan 2020 20:44:49 +0300 Subject: [PATCH 13/15] fix for cdl sram logging hack crashes nsf logging (fixed #94) --- src/drivers/win/cdlogger.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/drivers/win/cdlogger.cpp b/src/drivers/win/cdlogger.cpp index 73a5bc65..5fb12951 100644 --- a/src/drivers/win/cdlogger.cpp +++ b/src/drivers/win/cdlogger.cpp @@ -562,8 +562,10 @@ void InitCDLog() cdloggerVideoDataSize = CHRsize[0]; cdloggervdata = (unsigned char*)malloc(cdloggerVideoDataSize); } else { - cdloggerVideoDataSize = 0; - cdloggervdata = (unsigned char*)malloc(8192); + if (GameInfo->type != GIT_NSF) { + cdloggerVideoDataSize = 0; + cdloggervdata = (unsigned char*)malloc(8192); + } } } @@ -576,8 +578,10 @@ void ResetCDLog() undefinedvromcount = cdloggerVideoDataSize; ZeroMemory(cdloggervdata, cdloggerVideoDataSize); } else { - undefinedvromcount = 8192; - ZeroMemory(cdloggervdata, 8192); + if (GameInfo->type != GIT_NSF) { + undefinedvromcount = 8192; + ZeroMemory(cdloggervdata, 8192); + } } } From f83e488a655ff2245b7c0132b87d6cde9579b993 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 30 Jan 2020 18:26:52 -0500 Subject: [PATCH 14/15] Fixed type in lua-engine.cpp (#95) --- src/lua-engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lua-engine.cpp b/src/lua-engine.cpp index 6e65f6c5..1a5a7020 100644 --- a/src/lua-engine.cpp +++ b/src/lua-engine.cpp @@ -515,7 +515,7 @@ extern void ReloadRom(void); // emu.loadrom(string filename) // // Loads the rom from the directory relative to the lua script or from the absolute path. -// If the rom can't e loaded, loads the most recent one. +// If the rom can't be loaded, loads the most recent one. static int emu_loadrom(lua_State *L) { #ifdef WIN32 const char* str = lua_tostring(L,1); From e48b2089182d4a2ac41a2a1d10e90b74089d9636 Mon Sep 17 00:00:00 2001 From: Devine Lu Linvega Date: Thu, 30 Jan 2020 18:27:21 -0500 Subject: [PATCH 15/15] Fix typo in LuaFunctionsList.html (#96) --- web/help/LuaFunctionsList.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/help/LuaFunctionsList.html b/web/help/LuaFunctionsList.html index 126f3618..44b06457 100644 --- a/web/help/LuaFunctionsList.html +++ b/web/help/LuaFunctionsList.html @@ -158,7 +158,7 @@


Loads the ROM from the directory relative to the lua script or from the absolute path. Hence, the filename parameter can be absolute or relative path.


-

If the ROM can't e loaded, loads the most recent one.

+

If the ROM can't be loaded, loads the most recent one.


emu.registerbefore(function func)