From 2b2d70b221347c6c08169d1a51f12453d10b1180 Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 8 Aug 2008 09:45:34 +0000 Subject: [PATCH] - fiddle with nametable viewer to display correct NT,CHR,ATTR data in more cases (specifically, including some exotic mmc5 cases). - fix a new bug in windows build which caused fourscore emulation to fail in some cases --- changelog.txt | 3 + src/driver.h | 2 +- src/drivers/win/input.cpp | 94 +++++++++---- src/drivers/win/input.h | 1 - src/drivers/win/ntview.cpp | 282 +++++++++++++++---------------------- src/ppu.cpp | 44 ++++-- src/ppu.h | 1 + src/pputile.h | 103 -------------- src/pputile.inc | 101 +++++++++++++ vc8/fceux.vcproj | 218 ++++++++++++++-------------- 10 files changed, 426 insertions(+), 423 deletions(-) delete mode 100644 src/pputile.h create mode 100644 src/pputile.inc diff --git a/changelog.txt b/changelog.txt index 37c844a2..03a63342 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,8 @@ ---version 2.0.2 released--- +08-aug-2008 - zeromus - fiddle with nametable viewer to display correct NT,CHR,ATTR data in more cases (specifically, including some exotic mmc5 cases). +08-aug-2008 - zeromus - fix a new bug in windows build which caused fourscore emulation to fail in some cases +07-aug-2008 - zeromus - add an option to pick a constant color to draw in place of BG when BG rendering is disabled (look for gNoBGFillColor in config; 255 means to use palette[0]) 07-aug-2008 - adelikat - added a mute turbo option in sound config 07-aug-2008 - adelikat - new toggle - frame adv. - lag skip (menu item + hotkey mapping + saved in config) 07-aug-2008 - adelikat - put in -32000 protection on all dialogs that remember x,y diff --git a/src/driver.h b/src/driver.h index 80ca2914..79731104 100644 --- a/src/driver.h +++ b/src/driver.h @@ -304,7 +304,7 @@ void FCEUD_DebugBreakpoint(); void FCEUD_TraceInstruction(); ///the driver might should update its NTView (only used if debugging support is compiled in) -void FCEUD_UpdateNTView(int scanline, int drawall); +void FCEUD_UpdateNTView(int scanline, bool drawall); ///the driver might should update its PPUView (only used if debugging support is compiled in) void FCEUD_UpdatePPUView(int scanline, int drawall); diff --git a/src/drivers/win/input.cpp b/src/drivers/win/input.cpp index 44a842ad..a9f6f1e7 100644 --- a/src/drivers/win/input.cpp +++ b/src/drivers/win/input.cpp @@ -38,6 +38,8 @@ LPDIRECTINPUT7 lpDI=0; +void InitInputPorts(bool fourscore); + //UsrInputType[] is user-specified. InputType[] is current // (game/savestate/movie loading can override user settings) @@ -74,7 +76,7 @@ void ParseGIInput(FCEUGI *gi) if(gi->inputfc!=SIFC_UNSET) InputType[2]=gi->inputfc; - InitInputPorts(); + InitInputPorts((eoptions & EO_FOURSCORE)!=0); } } @@ -370,55 +372,85 @@ void FCEUD_SetInput(bool fourscore, ESI port0, ESI port1, ESIFC fcexp) InputType[0]=port0; InputType[1]=port1; InputType[2]=fcexp; - InitInputPorts(); + InitInputPorts(fourscore); } //Initializes the emulator with the current input port configuration -void InitInputPorts() +void InitInputPorts(bool fourscore) { void *InputDPtr; - int t; - int x; int attrib; - for(t=0,x=0;x<2;x++) - { - attrib=0; - InputDPtr=0; - switch(InputType[x]) + if(fourscore) { + FCEUI_SetInput(0,SI_GAMEPAD,&JSreturn,0); + FCEUI_SetInput(1,SI_GAMEPAD,&JSreturn,0); + } else { + for(int i=0;i<2;i++) { - case SI_POWERPADA: - case SI_POWERPADB:InputDPtr=&powerpadbuf[x];break; - case SI_GAMEPAD:InputDPtr=&JSreturn;break; - case SI_ARKANOID:InputDPtr=MouseData;t|=1;break; - case SI_ZAPPER:InputDPtr=MouseData; - t|=1; - break; + attrib=0; + InputDPtr=0; + switch(InputType[i]) + { + case SI_POWERPADA: + case SI_POWERPADB: + InputDPtr=&powerpadbuf[i]; + break; + case SI_GAMEPAD: + InputDPtr=&JSreturn; + break; + case SI_ARKANOID: + InputDPtr=MouseData; + break; + case SI_ZAPPER: + InputDPtr=MouseData; + break; + } + FCEUI_SetInput(i,(ESI)InputType[i],InputDPtr,attrib); } - FCEUI_SetInput(x,(ESI)InputType[x],InputDPtr,attrib); } attrib=0; InputDPtr=0; switch(InputType[2]) { - case SIFC_SHADOW:InputDPtr=MouseData;t|=1;break; - case SIFC_OEKAKIDS:InputDPtr=MouseData;t|=1;break; - case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break; - case SIFC_FKB:InputDPtr=fkbkeys;break; - case SIFC_SUBORKB:InputDPtr=suborkbkeys;break; - case SIFC_HYPERSHOT:InputDPtr=&HyperShotData;break; - case SIFC_MAHJONG:InputDPtr=&MahjongData;break; - case SIFC_QUIZKING:InputDPtr=&QuizKingData;break; - case SIFC_TOPRIDER:InputDPtr=&TopRiderData;break; - case SIFC_BWORLD:InputDPtr=BWorldData;break; + case SIFC_SHADOW: + InputDPtr=MouseData; + break; + case SIFC_OEKAKIDS: + InputDPtr=MouseData; + break; + case SIFC_ARKANOID: + InputDPtr=MouseData; + break; + case SIFC_FKB: + InputDPtr=fkbkeys; + break; + case SIFC_SUBORKB: + InputDPtr=suborkbkeys; + break; + case SIFC_HYPERSHOT: + InputDPtr=&HyperShotData; + break; + case SIFC_MAHJONG: + InputDPtr=&MahjongData; + break; + case SIFC_QUIZKING: + InputDPtr=&QuizKingData; + break; + case SIFC_TOPRIDER: + InputDPtr=&TopRiderData; + break; + case SIFC_BWORLD: + InputDPtr=BWorldData; + break; case SIFC_FTRAINERA: - case SIFC_FTRAINERB:InputDPtr=&FTrainerData;break; + case SIFC_FTRAINERB: + InputDPtr=&FTrainerData; + break; } FCEUI_SetInputFC((ESIFC)InputType[2],InputDPtr,attrib); - FCEUI_SetInputFourscore((eoptions&EO_FOURSCORE)!=0); } ButtConfig fkbmap[0x48]= @@ -1352,7 +1384,7 @@ void ConfigInput(HWND hParent) //in case the input config changes while a game is running, reconfigure the input ports if(GameInfo) { - InitInputPorts(); + InitInputPorts((eoptions & EO_FOURSCORE)!=0); } } diff --git a/src/drivers/win/input.h b/src/drivers/win/input.h index 1ed3057b..79d0b6c3 100644 --- a/src/drivers/win/input.h +++ b/src/drivers/win/input.h @@ -58,7 +58,6 @@ void ParseGIInput(FCEUGI *GameInfo); #define FCFGD_HYPERSHOT 3 #define FCFGD_QUIZKING 4 -void InitInputPorts(); void SetEmulationSpeed(int type); int FCEUD_TestCommandState(int c); void FCEUD_UpdateInput(); diff --git a/src/drivers/win/ntview.cpp b/src/drivers/win/ntview.cpp index 162e289d..b2611790 100644 --- a/src/drivers/win/ntview.cpp +++ b/src/drivers/win/ntview.cpp @@ -18,6 +18,19 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* +zeromus's ruminations on the ntview: +nothing in the emu internals really tracks mirroring. +all we really know at any point is what is pointed to by each vnapage[4] +So if the ntview is to let a person change the mapping, it needs to infer the mapping mode +by looking at vnapages and adjust them as the user sees fit. +This was all working before I got here. +However, the rendering system was relying on a notion of mirroring modes, which was a mistake. +It should, instead, rely strictly on the vnapages. +Since it has a caching mechanism, the cache needs to track what vnapage it thinks it is caching, +and invalidate it when the vnapage changes. +*/ + #include "common.h" #include "ntview.h" #include "debugger.h" @@ -34,16 +47,26 @@ HWND hNTView; int NTViewPosX,NTViewPosY; static uint8 palcache[32]; //palette cache //mbg merge 7/19/06 needed to be static -//uint8 ntcache0[0x400],ntcache1[0x400],ntcache2[0x400],ntcache3[0x400]; //cache CHR, fixes a refresh problem when right-clicking -uint8 *ntable0, *ntable1, *ntable2, *ntable3; //name table bitmap array -uint8 *ntablemirr[4]; -uint8 ntcache[4][0x400]; //todo: use an array for the above variables too int NTViewScanline=0,NTViewer=0; int NTViewSkip,NTViewRefresh; static int mouse_x,mouse_y; //todo: is static needed here? --mbg 7/19/06 - i think so -int redrawtables = 0; +bool redrawtables = false; int chrchanged = 0; +static class NTCache { +public: + NTCache() + : curr_vnapage(0) + {} + + uint8* curr_vnapage; + uint8* bitmap; + uint8 cache[0x400]; + HDC hdc; + HBITMAP hbmp; + HGDIOBJ tmpobj; +} cache[4]; + enum NT_MirrorType { NT_NONE = -1, NT_HORIZONTAL, NT_VERTICAL, NT_FOUR_SCREEN, @@ -76,13 +99,7 @@ void UpdateMirroringButtons(); void ChangeMirroring(); static BITMAPINFO bmInfo; //todo is static needed here so it won't interefere with the pattern table viewer? -static HDC pDC,TmpDC0,TmpDC1; -static HBITMAP TmpBmp0,TmpBmp1; -static HGDIOBJ TmpObj0,TmpObj1; - -static HDC TmpDC2,TmpDC3; -static HBITMAP TmpBmp2,TmpBmp3; -static HGDIOBJ TmpObj2,TmpObj3; +static HDC pDC; extern uint32 TempAddr, RefreshAddr; extern uint8 XOffset; @@ -91,7 +108,7 @@ int xpos, ypos; int scrolllines = 1; //if you pass this 1 then it will draw no matter what. If you pass it 0 -//then it will draw if redrawtables is 1 +//then it will draw if redrawtables is true void NTViewDoBlit(int autorefresh) { if (!hNTView) return; if (NTViewSkip < NTViewRefresh) { @@ -101,96 +118,13 @@ void NTViewDoBlit(int autorefresh) { NTViewSkip=0; if((redrawtables && !autorefresh) || (autorefresh) || (scrolllines)){ - //todo: use switch and use bitblt for because its faster - switch(ntmirroring){ - case NT_HORIZONTAL: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - break; - case NT_VERTICAL: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - break; - case NT_FOUR_SCREEN: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC2,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC3,0,0,SRCCOPY); - break; - case NT_SINGLE_SCREEN_TABLE_0: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC0,0,0,SRCCOPY); - break; - case NT_SINGLE_SCREEN_TABLE_1: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC1,0,0,SRCCOPY); - break; - case NT_SINGLE_SCREEN_TABLE_2: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC2,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC2,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC2,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC2,0,0,SRCCOPY); - break; - case NT_SINGLE_SCREEN_TABLE_3: - BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC3,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,TmpDC3,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC3,0,0,SRCCOPY); - BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,TmpDC3,0,0,SRCCOPY); - break; - } - /* - if(ntmirroring == NT_HORIZONTAL){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_VERTICAL){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_FOUR_SCREEN){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC2,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC3,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_SINGLE_SCREEN_TABLE_0){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC0,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_SINGLE_SCREEN_TABLE_1){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC1,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_SINGLE_SCREEN_TABLE_2){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC2,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC2,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC2,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC2,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - if(ntmirroring == NT_SINGLE_SCREEN_TABLE_3){ - StretchBlt(pDC,NTDESTX,NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC3,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY,NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC3,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX,NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC3,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - StretchBlt(pDC,NTDESTX+(NTWIDTH*ZOOM),NTDESTY+(NTHEIGHT*ZOOM),NTWIDTH*ZOOM,NTHEIGHT*ZOOM,TmpDC3,0,NTHEIGHT-1,NTWIDTH,-NTHEIGHT,SRCCOPY); - } - */ - redrawtables = 0; + + BitBlt(pDC,NTDESTX,NTDESTY,NTWIDTH,NTHEIGHT,cache[0].hdc,0,0,SRCCOPY); + BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY,NTWIDTH,NTHEIGHT,cache[1].hdc,0,0,SRCCOPY); + BitBlt(pDC,NTDESTX,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,cache[2].hdc,0,0,SRCCOPY); + BitBlt(pDC,NTDESTX+NTWIDTH,NTDESTY+NTHEIGHT,NTWIDTH,NTHEIGHT,cache[3].hdc,0,0,SRCCOPY); + + redrawtables = false; } if(scrolllines){ @@ -280,24 +214,40 @@ INLINE void DrawChr(uint8 *pbitmap,uint8 *chr,int pal){ //pbitmap -= (((PALETTEBITWIDTH>>2)<<3)-24); } -void DrawNameTable(uint8 *bitmap, uint8 *table, uint8 *tablecache) { - int x,y,a, chr, ptable=0, cacheaddr0, cacheaddr1;//index=0; +void DrawNameTable(int scanline, int ntnum, bool invalidateCache) { + + NTCache &c = cache[ntnum]; + uint8 *bitmap = c.bitmap, *table = vnapage[ntnum], *tablecache = c.cache; + + int a, ptable=0; uint8 *pbitmap = bitmap; if(PPU[0]&0x10){ //use the correct pattern table based on this bit ptable=0x1000; } + bool invalid = invalidateCache; + //if we werent asked to invalidate the cache, maybe we need to invalidate it anyway due to vnapage changing + if(!invalid) + invalid = (c.curr_vnapage != vnapage[ntnum]); + c.curr_vnapage = vnapage[ntnum]; + + //HACK: never cache anything + //invalid = true; + pbitmap = bitmap; - for(y = 0;y < 30;y++){ - for(x = 0;x < 32;x++){ - cacheaddr0 = (y*32)+x; - cacheaddr1 = 0x3C0+((y>>2)<<3)+(x>>2); - if((tablecache == 0) || (table[cacheaddr0] != tablecache[cacheaddr0]) || - (table[cacheaddr1] != tablecache[cacheaddr1])){ - redrawtables = 1; - a = (table[0x3C0+((y>>2)<<3)+(x>>2)] & (3<<(((y&2)<<1)+(x&2)))) >> (((y&2)<<1)+(x&2)); - //the commented out code below is all equilivent to the single line above. + for(int y=0;y<30;y++){ + for(int x=0;x<32;x++){ + int ntaddr = (y*32)+x; + int attraddr = 0x3C0+((y>>2)<<3)+(x>>2); + if(invalid + || (table[ntaddr] != tablecache[ntaddr]) + || (table[attraddr] != tablecache[attraddr])) { + redrawtables = true; + int temp = (((y&2)<<1)+(x&2)); + a = (table[attraddr] & (3<> temp; + + //the commented out code below is all allegedly equivalent to the single line above: //tmpx = x>>2; //tmpy = y>>2; //a = 0x3C0+(tmpy*8)+tmpx; @@ -306,24 +256,42 @@ void DrawNameTable(uint8 *bitmap, uint8 *table, uint8 *tablecache) { //if((((x>>1)&1) == 0) && (((y>>1)&1) == 1)) a = (table[a]&0x30)>>4; //if((((x>>1)&1) == 1) && (((y>>1)&1) == 1)) a = (table[a]&0xC0)>>6; - chr = table[y*32+x]*16; - DrawChr(pbitmap,&VPage[(ptable+chr)>>10][ptable+chr],a); - if(tablecache != 0){ - tablecache[cacheaddr0] = table[cacheaddr0]; - //tablecache[cacheaddr1] = table[cacheaddr1]; - } + int chr = table[ntaddr]*16; + + extern int FCEUPPU_GetAttr(int ntnum, int xt, int yt); + + //test.. instead of pretending that the nametable is a screen at 0,0 we pretend that it is at the current xscroll and yscroll + //int xpos = ((RefreshAddr & 0x400) >> 2) | ((RefreshAddr & 0x1F) << 3) | XOffset; + //int ypos = ((RefreshAddr & 0x3E0) >> 2) | ((RefreshAddr & 0x7000) >> 12); + //if(RefreshAddr & 0x800) ypos += 240; + //int refreshaddr = (xpos/8+x)+(ypos/8+y)*32; + + int refreshaddr = (x)+(y)*32; + + a = FCEUPPU_GetAttr(ntnum,x,y); + + //a good way to do it: + DrawChr(pbitmap,FCEUPPU_GetCHR(ptable+chr,refreshaddr),a); + + tablecache[ntaddr] = table[ntaddr]; + tablecache[attraddr] = table[attraddr]; + //one could comment out the line above... + //since there are so many fewer attribute values than NT values, it might be best just to refresh the whole attr table below with the memcpy + + //obviously this whole scheme of nt cache doesnt work if an mmc5 game is playing tricks with the attribute table } pbitmap += (8*3); } pbitmap += 7*((NTWIDTH*3)); } - if((tablecache != 0) && (redrawtables)){ //this copies the attribute tables to the cache if needed - memcpy(tablecache+0x3c0,table+0x3c0,0x40); - } + //this copies the attribute tables to the cache if needed. but we arent using it now because + //if(redrawtables){ + // memcpy(tablecache+0x3c0,table+0x3c0,0x40); + //} } -void FCEUD_UpdateNTView(int scanline, int drawall) { +void FCEUD_UpdateNTView(int scanline, bool drawall) { if(!NTViewer) return; if(scanline != -1 && scanline != NTViewScanline) return; @@ -349,8 +317,7 @@ void FCEUD_UpdateNTView(int scanline, int drawall) { memcpy(palcache,PALRAM,32); drawall = 1; //palette has changed, so redraw all } - - + ntmirroring = NT_NONE; if(vnapage[0] == vnapage[1])ntmirroring = NT_HORIZONTAL; if(vnapage[0] == vnapage[2])ntmirroring = NT_VERTICAL; @@ -368,21 +335,8 @@ void FCEUD_UpdateNTView(int scanline, int drawall) { oldntmirroring = ntmirroring; } - if(drawall){ - DrawNameTable(ntable0,&NTARAM[0x000],0); - DrawNameTable(ntable1,&NTARAM[0x400],0); - DrawNameTable(ntable2,ExtraNTARAM,0); - DrawNameTable(ntable3,ExtraNTARAM+0x400,0); - } else { - if(ntmirroring == NT_HORIZONTAL || ntmirroring == NT_VERTICAL || ntmirroring == NT_SINGLE_SCREEN_TABLE_0) - DrawNameTable(ntable0,&NTARAM[0x000],ntcache[0]); - if(ntmirroring == NT_HORIZONTAL || ntmirroring == NT_VERTICAL || ntmirroring == NT_SINGLE_SCREEN_TABLE_1) - DrawNameTable(ntable1,&NTARAM[0x400],ntcache[1]); - if(ntmirroring == NT_FOUR_SCREEN){ - DrawNameTable(ntable2,ExtraNTARAM,ntcache[2]); - DrawNameTable(ntable3,ExtraNTARAM+0x400,ntcache[3]); - } - } + for(int i=0;i<4;i++) + DrawNameTable(scanline,i,drawall); chrchanged = 0; @@ -391,18 +345,12 @@ void FCEUD_UpdateNTView(int scanline, int drawall) { void KillNTView() { //GDI cleanup - DeleteObject(TmpBmp0); - SelectObject(TmpDC0,TmpObj0); - DeleteDC(TmpDC0); - DeleteObject(TmpBmp1); - SelectObject(TmpDC1,TmpObj1); - DeleteDC(TmpDC1); - DeleteObject(TmpBmp2); - SelectObject(TmpDC2,TmpObj2); - DeleteDC(TmpDC2); - DeleteObject(TmpBmp3); - SelectObject(TmpDC3,TmpObj3); - DeleteDC(TmpDC3); + for(int i=0;i<4;i++) { + DeleteObject(cache[i].hbmp); + SelectObject(cache[i].hdc,cache[i].tmpobj); + DeleteDC(cache[i].hdc); + } + ReleaseDC(hNTView,pDC); DeleteObject (SelectObject (pDC, GetStockObject (BLACK_PEN))) ; @@ -435,21 +383,12 @@ BOOL CALLBACK NTViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) //create memory dcs pDC = GetDC(hwndDlg); // GetDC(GetDlgItem(hwndDlg,IDC_NTVIEW_TABLE_BOX)); - TmpDC0 = CreateCompatibleDC(pDC); //name table 0 - TmpDC1 = CreateCompatibleDC(pDC); //name table 1 - TmpDC2 = CreateCompatibleDC(pDC); //name table 2 - TmpDC3 = CreateCompatibleDC(pDC); //name table 3 - //TmpDC2 = CreateCompatibleDC(pDC); //palettes - - //create bitmaps and select them into the memory dc's - TmpBmp0 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&ntable0,0,0); - TmpObj0 = SelectObject(TmpDC0,TmpBmp0); - TmpBmp1 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&ntable1,0,0); - TmpObj1 = SelectObject(TmpDC1,TmpBmp1); - TmpBmp2 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&ntable2,0,0); - TmpObj2 = SelectObject(TmpDC2,TmpBmp2); - TmpBmp3 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&ntable3,0,0); - TmpObj3 = SelectObject(TmpDC3,TmpBmp3); + for(int i=0;i<4;i++) { + NTCache &c = cache[i]; + c.hdc = CreateCompatibleDC(pDC); + c.hbmp = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&c.bitmap,0,0); + c.tmpobj = SelectObject(c.hdc,c.hbmp); + } //Refresh Trackbar SendDlgItemMessage(hwndDlg,IDC_NTVIEW_REFRESH_TRACKBAR,TBM_SETRANGE,0,(LPARAM)MAKELONG(0,25)); @@ -602,10 +541,13 @@ void DoNTView() { return; } - if (!hNTView) hNTView = CreateDialog(fceu_hInstance,"NTVIEW",NULL,NTViewCallB); + if (!hNTView) { + hNTView = CreateDialog(fceu_hInstance,"NTVIEW",NULL,NTViewCallB); + new(cache) NTCache[4]; //reinitialize NTCache + } if (hNTView) { SetWindowPos(hNTView,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER); - FCEUD_UpdateNTView(-1,1); + FCEUD_UpdateNTView(-1,true); NTViewDoBlit(1); } } diff --git a/src/ppu.cpp b/src/ppu.cpp index 464b1cca..484c65fa 100644 --- a/src/ppu.cpp +++ b/src/ppu.cpp @@ -165,6 +165,34 @@ uint8 * MMC5BGVRAMADR(uint32 V) { } else return &MMC5BGVPage[(V)>>10][(V)]; } +//this duplicates logic which is embedded in the ppu rendering code +//which figures out where to get CHR data from depending on various hack modes +//mostly involving mmc5. +//this might be incomplete. +uint8* FCEUPPU_GetCHR(uint32 vadr, uint32 refreshaddr) { + if(MMC5Hack) { + if(MMC5HackCHRMode==1) { + uint8 *C = MMC5HackVROMPTR; + C += (((MMC5HackExNTARAMPtr[refreshaddr & 0x3ff]) & 0x3f & MMC5HackVROMMask) << 12) + (vadr & 0xfff); + return C; + } else { + return MMC5BGVRAMADR(vadr); + } + } + else return VRAMADR(vadr); +} + +//likewise for ATTR +int FCEUPPU_GetAttr(int ntnum, int xt, int yt) { + int attraddr = 0x3C0+((yt>>2)<<3)+(xt>>2); + int temp = (((yt&2)<<1)+(xt&2)); + int refreshaddr = xt+yt*32; + if(MMC5Hack && MMC5HackCHRMode==1) + return (MMC5HackExNTARAMPtr[refreshaddr & 0x3ff] & 0xC0)>>6; + else + return (vnapage[ntnum][attraddr] & (3<> temp; +} + static DECLFR(A2002) { uint8 ret; @@ -469,7 +497,7 @@ void FCEUI_GetRenderPlanes(bool& sprites, bool& bg) // //if((vadr+turt*8192)>=524288) // //printf("%d ",vadr+turt*8192); // cc=0; -// //#include "pputile.h" +// //#include "pputile.inc" // } //} @@ -601,12 +629,12 @@ static void RefreshLine(int lastpixel) if((tochange<=0 && MMC5HackSPMode&0x40) || (tochange>0 && !(MMC5HackSPMode&0x40))) { #define PPUT_MMC5SP -#include "pputile.h" +#include "pputile.inc" #undef PPUT_MMC5SP } else { -#include "pputile.h" +#include "pputile.inc" } tochange--; } @@ -620,7 +648,7 @@ static void RefreshLine(int lastpixel) #define PPUT_MMC5CHR1 for(X1=firsttile;X1>3)+MMC5HackSPScroll)&0x1F; - if(ys>=0x1E) ys-=0x1E; - #endif - - 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)]; - //printf("%02x ",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; - } - - #ifdef PPUT_MMC5SP - vadr=(MMC5HackExNTARAMPtr[xs|(ys<<5)]<<4)+(vofs&7); - #else - zz=RefreshAddr&0x1F; - C=vnapage[(RefreshAddr>>10)&3]; - vadr=(C[RefreshAddr&0x3ff]<<4)+vofs; /* Fetch name table byte. */ - #endif - - #ifdef PPUT_HOOK - PPU_hook(0x2000|(RefreshAddr&0xfff)); - #endif - - #ifdef PPUT_MMC5SP - cc=MMC5HackExNTARAMPtr[0x3c0+(xs>>2)+((ys&0x1C)<<1)]; - cc=((cc >> ((xs&2) + ((ys&0x2)<<1))) &3); - #else - #ifdef PPUT_MMC5CHR1 - cc=(MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff] & 0xC0)>>6; - #else - cc=C[0x3c0+(zz>>2)+((RefreshAddr&0x380)>>4)]; /* Fetch attribute table byte. */ - cc=((cc >> ((zz&2) + ((RefreshAddr&0x40)>>4))) &3); - #endif - #endif - - atlatch>>=2; - atlatch|=cc<<2; - - pshift[0]<<=8; - pshift[1]<<=8; - - #ifdef PPUT_MMC5SP - C = MMC5HackVROMPTR+vadr; - C += ((MMC5HackSPPage & 0x3f & MMC5HackVROMMask) << 12); - #else - #ifdef PPUT_MMC5CHR1 - C = MMC5HackVROMPTR; - C += (((MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff]) & 0x3f & - MMC5HackVROMMask) << 12) + (vadr & 0xfff); - #elif defined(PPUT_MMC5) - C=MMC5BGVRAMADR(vadr); - #else - C = VRAMADR(vadr); - #endif - #endif - - #ifdef PPUT_HOOK - PPU_hook(vadr); - #endif - - pshift[0]|=C[0]; - pshift[1]|=C[8]; - - if((RefreshAddr&0x1f)==0x1f) - RefreshAddr^=0x41F; - else - RefreshAddr++; - - #ifdef PPUT_HOOK - PPU_hook(0x2000|(RefreshAddr&0xfff)); - #endif - diff --git a/src/pputile.inc b/src/pputile.inc new file mode 100644 index 00000000..7eacb593 --- /dev/null +++ b/src/pputile.inc @@ -0,0 +1,101 @@ +uint8 *C; +register uint8 cc; +uint32 vadr; + +#ifndef PPUT_MMC5SP + uint8 zz; +#else + uint8 xs,ys; + xs=X1; + ys=((scanline>>3)+MMC5HackSPScroll)&0x1F; + if(ys>=0x1E) ys-=0x1E; +#endif + +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)]; + //printf("%02x ",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; +} + +#ifdef PPUT_MMC5SP + vadr=(MMC5HackExNTARAMPtr[xs|(ys<<5)]<<4)+(vofs&7); +#else + zz=RefreshAddr&0x1F; + C=vnapage[(RefreshAddr>>10)&3]; + vadr=(C[RefreshAddr&0x3ff]<<4)+vofs; /* Fetch name table byte. */ +#endif + +#ifdef PPUT_HOOK + PPU_hook(0x2000|(RefreshAddr&0xfff)); +#endif + +#ifdef PPUT_MMC5SP + cc=MMC5HackExNTARAMPtr[0x3c0+(xs>>2)+((ys&0x1C)<<1)]; + cc=((cc >> ((xs&2) + ((ys&0x2)<<1))) &3); +#else + #ifdef PPUT_MMC5CHR1 + cc=(MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff] & 0xC0)>>6; + #else + cc=C[0x3c0+(zz>>2)+((RefreshAddr&0x380)>>4)]; /* Fetch attribute table byte. */ + cc=((cc >> ((zz&2) + ((RefreshAddr&0x40)>>4))) &3); + #endif +#endif + +atlatch>>=2; +atlatch|=cc<<2; + +pshift[0]<<=8; +pshift[1]<<=8; + +#ifdef PPUT_MMC5SP + C = MMC5HackVROMPTR+vadr; + C += ((MMC5HackSPPage & 0x3f & MMC5HackVROMMask) << 12); +#else + #ifdef PPUT_MMC5CHR1 + C = MMC5HackVROMPTR; + C += (((MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff]) & 0x3f & + MMC5HackVROMMask) << 12) + (vadr & 0xfff); + #elif defined(PPUT_MMC5) + C=MMC5BGVRAMADR(vadr); + #else + C = VRAMADR(vadr); + #endif +#endif + +#ifdef PPUT_HOOK + PPU_hook(vadr); +#endif + +pshift[0]|=C[0]; +pshift[1]|=C[8]; + +if((RefreshAddr&0x1f)==0x1f) + RefreshAddr^=0x41F; +else + RefreshAddr++; + +#ifdef PPUT_HOOK + PPU_hook(0x2000|(RefreshAddr&0xfff)); +#endif + diff --git a/vc8/fceux.vcproj b/vc8/fceux.vcproj index cc6ce9b8..c6af6292 100644 --- a/vc8/fceux.vcproj +++ b/vc8/fceux.vcproj @@ -103,88 +103,6 @@ CommandLine="xcopy /y /d "$(ProjectDir)\..\src\drivers\win\7z.dll" "$(OutDir)" " /> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - @@ -2060,7 +2056,7 @@ /> - - - @@ -2243,6 +2230,15 @@ CompileAs="1" /> + + + @@ -2294,7 +2290,7 @@ /> + +