From 1cca98563b83a4764eb9cd83002a69eaf1ee02dc Mon Sep 17 00:00:00 2001 From: n-a-c-h <> Date: Mon, 18 Aug 2003 20:13:58 +0000 Subject: [PATCH] Updated IPS code. Now supports RLE, should fix problems if the ROM is expanded, and automatically view the ROM with a header. --- zsnes/src/Makefile.in | 4 +- zsnes/src/init.asm | 173 ++--------------------------------------- zsnes/src/link.win32 | 3 +- zsnes/src/makefile.dos | 4 +- zsnes/src/makefile.win | 5 +- zsnes/src/patch.c | 123 +++++++++++++++++++++++++++++ 6 files changed, 142 insertions(+), 170 deletions(-) create mode 100644 zsnes/src/patch.c diff --git a/zsnes/src/Makefile.in b/zsnes/src/Makefile.in index 6f4985b8..538b6662 100644 --- a/zsnes/src/Makefile.in +++ b/zsnes/src/Makefile.in @@ -57,7 +57,7 @@ WINDOSOBJ=${DOSDIR}/debug.o ${DOSDIR}/joy.o ${DOSDIR}/modemrtn.o ${DOSDIR}/vesa2 ZIPOBJ=${ZIPDIR}/zzip.o ${ZIPDIR}/unzip.o ${ZIPDIR}/zpng.o -MAINOBJ=cfgload.o endmem.o fixsin.o init.o initc.o ui.o vcache.o water.o smoke.o burn.o version.o +MAINOBJ=cfgload.o endmem.o fixsin.o init.o initc.o patch.o ui.o vcache.o water.o smoke.o burn.o version.o OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${ZIPOBJ} ${MAINOBJ} @@ -96,6 +96,7 @@ ui.o: ui.asm macros.mac cfgload.o:cfgload.asm macros.mac init.o:init.asm macros.mac initc.o:initc.c +patch.o:patch.c ALL: rm -f version.o @@ -192,3 +193,4 @@ distclean: rm -f ${CHIPDIR}/*.o ${CPUDIR}/*.o ${VIDEODIR}/*.o ${GUIDIR}/*.o ${DOSDIR}/*.o ${WINDIR}/*.o ${ZIPDIR}/*.o *.o @ZSNESEXE@ Makefile config.cache config.log config.status config.h + diff --git a/zsnes/src/init.asm b/zsnes/src/init.asm index 7dfc41c6..878ea332 100644 --- a/zsnes/src/init.asm +++ b/zsnes/src/init.asm @@ -95,7 +95,7 @@ EXTSYM GUIfindUSA,GUIfindEUR,GUIfindJAP,GUIfindZIP,GUIfind1,DTALoc,GUIfindall EXTSYM spc7110romptr,allocspc7110 EXTSYM SRAMDir,SRAMDrive,cfgloadsdir,fnamest,statefileloc EXTSYM ForcePal,ForceROMTiming,ForceHiLoROM,InitDir,InitDrive,enterpress,frameskip -EXTSYM maxromspace,curromspace,infoloc +EXTSYM maxromspace,curromspace,infoloc, patchfile EXTSYM gotoroot,headdata,printnum,romispal EXTSYM InitFxTables,SFXSRAM,SfxR1,SfxR2,SfxSCMR,SfxSFR,finterleave EXTSYM initregr,initregw,memtabler16,DSP1Read16b3F,memaccessbankr16 @@ -3642,63 +3642,12 @@ NEWSYM printhex8 ;******************************************************* ; Search for header size first which is filesize MOD 32768 -NEWSYM RetrieveDataIPS - xor ah,ah - cmp ecx,10000 - jne .notoverflow - push edx - push ecx - mov edx,wramdataa - mov ecx,10000 - call Read_File - cmp eax,0 - jne .notempty - mov ah,1 - jmp .empty -.notempty - xor ah,ah -.empty - pop ecx - pop edx - xor ecx,ecx -.notoverflow - mov al,[wramdataa+ecx] - inc ecx - ret - - -SECTION .bss -IPSSL resd 1 -SECTION .text - NEWSYM PatchIPS %ifdef __LINUX__ pushad call pushdir popad %endif - mov byte[IPSPatched],0 - mov dword[IPSOffset],0 - cmp byte[Header512],0 - je .no512head - mov dword[IPSOffset],512 -.no512head - mov dword[IPSLimit],4096*1024 - cmp byte[Sup48mbit],0 - je .not48 - mov dword[IPSLimit],6144*1024 -.not48 - cmp byte[Sup16mbit],0 - je .not16 - mov dword[IPSLimit],2048*1024 -.not16 - ; 1965-1970, >1969*1024+712 (812/850/1000) - ; upper bound: 1969*1024+1024 - ; between 1965-<1970 / 1968,1970 -; mov dword[IPSLimit],208062h -; mov dword[IPSSL],208832h - ; font = 208062h-208832h - mov eax,fname+1 ; search for . or 0 .next @@ -3737,113 +3686,14 @@ NEWSYM PatchIPS .nochangedir: %endif mov edx,fname+1 - call Open_File - jc near .failed - mov bx,ax - mov edx,Headchek - mov ecx,5 - call Read_File - cmp dword[Headchek],'PATC' - jne near .ipsfaileddet - cmp byte[Headchek+4],'H' - jne near .ipsfaileddet - mov ecx,10000 -.ipxloop -.findnext - xor edx,edx - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov dh,al - shl edx,8 - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov dh,al - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov dl,al - cmp edx,454F46h - je near .ipsokay - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - sub edx,[IPSOffset] - mov [IPSCount+1],al - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov [IPSCount],al - cmp word[IPSCount],0 - je .ipsclear -.loop - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed -; cmp edx,[IPSSL] -; jae .nolimit - cmp edx,[IPSLimit] - jae .limit -.nolimit - mov esi,[romdata] - mov [esi+edx],al -.limit - inc edx - dec word[IPSCount] - jnz .loop - jmp .findnext -.ipsclear - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov [IPSCount+1],al - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - mov [IPSCount],al - call RetrieveDataIPS - cmp ah,0 - jne near .ipsfailed - cmp word[IPSCount],0 - je near .findnext - mov esi,[romdata] -.loop2 - cmp edx,[IPSLimit] - jae .limit2 - mov [esi+edx],al -.limit2 - inc edx - dec word[IPSCount] - jnz .loop2 - jmp .findnext -.ipsokay - mov dword[Msgptr],.ipsokaymsg - mov dword[MessageOn],60*4 - mov byte[IPSPatched],1 - jmp .ipsfaileddet -.ipsfailed - mov dword[Msgptr],.ipsnokaymsg - mov dword[MessageOn],60*4 - mov byte[IPSPatched],1 -.ipsfaileddet - call Close_File -.failed + mov [patchfile],edx + EXTSYM PatchUsingIPS + pushad + call PatchUsingIPS + popad pop eax mov ebx,[Prevextn] mov [eax],ebx - ; font = 208062h-208832h -; mov esi,[romdata] -; mov [esi+208062h],0 - ;0-768, 3072-3072+256, 4096-4096+256 -; mov edx,2079*1024 ;+2048+2048*40 -; mov ecx,2048 -; mov esi,[romdata] -;.ltop -; mov byte[esi+edx],0 -; inc edx -; dec ecx -; jnz .ltop %ifdef __LINUX__ pushad call popdir @@ -3851,18 +3701,10 @@ NEWSYM PatchIPS %endif ret -SECTION .data -.ipsokaymsg db 'IPS PATCHED.',0 -.ipsnokaymsg db 'IPS IS CORRUPT.',0 - SECTION .bss NEWSYM Header512, resb 1 NEWSYM Prevextn, resd 1 -NEWSYM Headchek, resb 5 -NEWSYM IPSLimit, resd 1 -NEWSYM IPSOffset, resd 1 -NEWSYM IPSCount, resd 1 -IPSPatched resb 1 +NEWSYM IPSPatched, resb 1 SECTION .text OpenCombFile: @@ -6367,3 +6209,4 @@ SECTION .text NEWSYM InitAsmEnd + diff --git a/zsnes/src/link.win32 b/zsnes/src/link.win32 index 302fdd42..de4bb93a 100644 --- a/zsnes/src/link.win32 +++ b/zsnes/src/link.win32 @@ -1,2 +1,3 @@ -/Fezsnesw.exe chips\dsp1proc.obj dos\sw.obj dos\gppro.obj dos\vesa12.obj dos\zsipx.obj dos\modemrtn.obj dos\joy.obj dos\debug.obj dos\vesa2.obj dos\initvid.obj cfgload.obj endmem.obj fixsin.obj init.obj initc.obj ui.obj vcache.obj water.obj smoke.obj burn.obj version.obj video\procvid.obj win\copyvwin.obj win\winintrf.obj win\winlink.obj win\zloaderw.obj win\ztcp.obj win\zfilew.obj win\zipxw.obj video\makev16b.obj video\makev16t.obj video\makevid.obj video\mode716.obj video\mode716b.obj video\mode716d.obj video\mode716e.obj video\mode716t.obj video\mode7.obj video\mode7ext.obj video\mv16tms.obj video\newg162.obj video\newgfx16.obj video\newgfx2.obj video\newgfx.obj video\m716text.obj video\2xsaiw.obj video\sw_draw.obj video/hq3x16.obj video/hq3x32.obj gui\gui.obj gui\menu.obj cpu\addrni.obj cpu\dma.obj cpu\dsp.obj cpu\dspproc.obj cpu\execute.obj cpu\irq.obj cpu\memory.obj cpu\spc700.obj cpu\stable.obj cpu\table.obj cpu\tableb.obj cpu\tablec.obj chips\dsp1emu.obj chips\fxemu2.obj chips\fxemu2b.obj chips\fxemu2c.obj chips\fxtable.obj chips\sa1proc.obj chips\sa1regs.obj chips\sfxproc.obj zip\unzip.obj zip\zzip.obj zip\zpng.obj zlib.lib libpng.lib wsock32.lib user32.lib gdi32.lib shell32.lib winmm.lib ddraw.lib dsound.lib dinput8.lib d3dx.lib /link /section:.text,erw +/Fezsnesw.exe chips\dsp1proc.obj dos\sw.obj dos\gppro.obj dos\vesa12.obj dos\zsipx.obj dos\modemrtn.obj dos\joy.obj dos\debug.obj dos\vesa2.obj dos\initvid.obj cfgload.obj endmem.obj fixsin.obj init.obj initc.obj patch.obj ui.obj vcache.obj water.obj smoke.obj burn.obj version.obj video\procvid.obj win\copyvwin.obj win\winintrf.obj win\winlink.obj win\zloaderw.obj win\ztcp.obj win\zfilew.obj win\zipxw.obj video\makev16b.obj video\makev16t.obj video\makevid.obj video\mode716.obj video\mode716b.obj video\mode716d.obj video\mode716e.obj video\mode716t.obj video\mode7.obj video\mode7ext.obj video\mv16tms.obj video\newg162.obj video\newgfx16.obj video\newgfx2.obj video\newgfx.obj video\m716text.obj video\2xsaiw.obj video\sw_draw.obj video/hq3x16.obj video/hq3x32.obj gui\gui.obj gui\menu.obj cpu\addrni.obj cpu\dma.obj cpu\dsp.obj cpu\dspproc.obj cpu\execute.obj cpu\irq.obj cpu\memory.obj cpu\spc700.obj cpu\stable.obj cpu\table.obj cpu\tableb.obj cpu\tablec.obj chips\dsp1emu.obj chips\fxemu2.obj chips\fxemu2b.obj chips\fxemu2c.obj chips\fxtable.obj chips\sa1proc.obj chips\sa1regs.obj chips\sfxproc.obj zip\unzip.obj zip\zzip.obj zip\zpng.obj zlib.lib libpng.lib wsock32.lib user32.lib gdi32.lib shell32.lib winmm.lib ddraw.lib dsound.lib dinput8.lib d3dx.lib /link /section:.text,erw + diff --git a/zsnes/src/makefile.dos b/zsnes/src/makefile.dos index 7a468336..d29422bf 100644 --- a/zsnes/src/makefile.dos +++ b/zsnes/src/makefile.dos @@ -55,7 +55,7 @@ PREOBJ=${OBJDIR}/dosbuff.o ${OBJDIR}/ipx.o ${OBJDIR}/zipx.o ZIPOBJ=${ZIPDIR}/zzip.o ${ZIPDIR}/unzip.o ${ZIPDIR}/zpng.o -MAINOBJ=cfgload.o endmem.o fixsin.o init.o initc.o ui.o vcache.o water.o smoke.o burn.o version.o +MAINOBJ=cfgload.o endmem.o fixsin.o init.o initc.o patch.o ui.o vcache.o water.o smoke.o burn.o version.o OBJS=${CHIPSOBJ} ${CPUOBJ} ${DOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${PREOBJ} ${MAINOBJ} ${ZIPOBJ} @@ -110,6 +110,7 @@ ui.o: ui.asm macros.mac cfgload.o:cfgload.asm macros.mac init.o:init.asm macros.mac initc.o:initc.c +patch.o:patch.c ALL: del version.o @@ -203,3 +204,4 @@ clean: del zsnes.exe + diff --git a/zsnes/src/makefile.win b/zsnes/src/makefile.win index 07339537..01cd78b9 100644 --- a/zsnes/src/makefile.win +++ b/zsnes/src/makefile.win @@ -64,7 +64,7 @@ PREOBJ= ZIPOBJ=${ZIPDIR}/zzip.obj ${ZIPDIR}/unzip.obj ${ZIPDIR}/zpng.obj -MAINOBJ=cfgload.obj endmem.obj fixsin.obj init.obj initc.obj ui.obj vcache.obj water.obj smoke.obj burn.obj version.obj +MAINOBJ=cfgload.obj endmem.obj fixsin.obj init.obj initc.obj patch.obj ui.obj vcache.obj water.obj smoke.obj burn.obj version.obj OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${GUIOBJ} ${VIDEOBJ} ${ZIPOBJ} ${MAINOBJ} ${WINDOSOBJ} LIBS= @@ -131,7 +131,7 @@ ui.obj: ui.asm macros.mac cfgload.obj:cfgload.asm macros.mac init.obj:init.asm macros.mac initc.obj:initc.c - +patch.obj:patch.c ALL: del version.obj version.obj:version.c @@ -229,3 +229,4 @@ clean: + diff --git a/zsnes/src/patch.c b/zsnes/src/patch.c new file mode 100644 index 00000000..7537b03d --- /dev/null +++ b/zsnes/src/patch.c @@ -0,0 +1,123 @@ +/* +Copyright (C) 2003 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) + +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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include + +extern int maxromspace; +extern int curromspace; +extern int NumofBytes; +extern int NumofBanks; +extern unsigned int *romdata; +extern unsigned char IPSPatched; + +char *patchfile; + +void PatchUsingIPS() +{ + unsigned char *ROM = (unsigned char *)romdata; + int location = 0, length = 0; + + IPSPatched = 0; + + FILE *fp = 0; + fp = fopen(patchfile, "rb"); + if (!fp) { return; } + + //Yup, it's goto! :) + //See 'IPSDone:' for explanation + if (fgetc(fp) != 'P') { goto IPSDone; } + if (fgetc(fp) != 'A') { goto IPSDone; } + if (fgetc(fp) != 'T') { goto IPSDone; } + if (fgetc(fp) != 'C') { goto IPSDone; } + if (fgetc(fp) != 'H') { goto IPSDone; } + + while (!feof(fp)) + { + //Location is a 3 byte value (max 16MB) + int inloc = (fgetc(fp) << 16) | (fgetc(fp) << 8) | fgetc(fp); + + if (inloc == 0x454f46) //EOF + { + break; + } + + //We assume all IPS files are for ROMs with headers + location = inloc - 512; + + //Length is a 2 byte value (max 64KB) + length = (fgetc(fp) << 8) | fgetc(fp); + + if (length) // Not RLE + { + int i; + for (i = 0; i < length; i++, location++) + { + if (location >= 0) + { + if (location >= maxromspace) { goto IPSDone; } + ROM[location] = (unsigned char)fgetc(fp); + } + else + { + fgetc(fp); //Need to skip the bytes that write to header + } + } + } + else //RLE + { + int i; + unsigned char newVal; + length = (fgetc(fp) << 8) | fgetc(fp); + newVal = (unsigned char)fgetc(fp); + for (i = 0; i < length; i++, location++) + { + if (location >= 0) + { + if (location >= maxromspace) { goto IPSDone; } + ROM[location] = newVal; + } + } + } + } + + //We use gotos to break out of the nested loops, + //as well as a simple way to check for 'PATCH' in + //some cases like this one, goto is the way to go. + IPSDone: + + fclose(fp); + IPSPatched = 1; + + //Adjust size values if the ROM was expanded + if (location > curromspace && location <= maxromspace) + { + curromspace = location; + NumofBytes = location; + NumofBanks = NumofBytes/32768; + } + + /* + //Write out patched ROM + fp = fopen("zsnes.rom", "wb"); + if (!fp) { asm volatile("int $3"); } + fwrite(ROM, 1, curromspace, fp); + fclose(fp); + */ +} +