From 4cb8ec719dfa8ebb50fb82f6af88b97435a6f776 Mon Sep 17 00:00:00 2001 From: dborth Date: Thu, 16 Oct 2008 01:45:12 +0000 Subject: [PATCH] [What's New 2.0.3 - October 1, 2008] * Complete rewrite of loading code - FDS / UNIF / NSF support added! * VS games work (coin insert submitted by pakitovic) * Mapping of 'Special' commands - VS coin insert, FDS switch disk (default A) * 480p and DVD now available for GameCube * Improved stability - less crashes! --- Makefile.gc | 6 +- Makefile.wii | 6 +- readme.txt | 77 +++-- source/fceultra/state.c | 28 +- source/ngc/dvd.c | 361 +++++++---------------- source/ngc/dvd.h | 9 +- source/ngc/fceuconfig.h | 4 +- source/ngc/fceugc.c | 4 +- source/ngc/fceuload.c | 2 +- source/ngc/fceuram.c | 14 - source/ngc/fceustate.c | 11 - source/ngc/fileop.c | 110 +++---- source/ngc/fileop.h | 4 +- source/ngc/filesel.c | 225 +++------------ source/ngc/filesel.h | 5 +- source/ngc/gcunzip.c | 608 ++++++++++++++++++++++----------------- source/ngc/gcunzip.h | 9 +- source/ngc/gcvideo.c | 27 -- source/ngc/gcvideo.h | 1 - source/ngc/menu.c | 43 +-- source/ngc/menudraw.c | 4 +- source/ngc/pad.c | 65 ++--- source/ngc/pad.h | 4 +- source/ngc/preferences.c | 6 +- source/ngc/smbop.c | 93 ++---- source/ngc/smbop.h | 11 +- source/sz/7zDecode.c | 236 ++++++++------- source/sz/7zDecode.h | 6 +- source/sz/7zExtract.c | 58 ++-- source/sz/7zTypes.h | 14 +- 30 files changed, 848 insertions(+), 1203 deletions(-) diff --git a/Makefile.gc b/Makefile.gc index 2786675f..58cf2f06 100644 --- a/Makefile.gc +++ b/Makefile.gc @@ -21,7 +21,7 @@ BUILD := build_gc SOURCES := source/fceultra source/fceultra/boards \ source/fceultra/drivers/common source/fceultra/input \ source/fceultra/mappers source/fceultra/mbshare \ - source/ngc source/sz + source/ngc DATA := data INCLUDES := source/fceultra source/ngc LANG := ENGLISH # Supported languages: ENGLISH @@ -29,7 +29,7 @@ LANG := ENGLISH # Supported languages: ENGLISH #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) -DNGC \ +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -DNGC \ -DHAVE_ASPRINTF -DSTDC -DFCEU_VERSION_NUMERIC=9812 \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ -DLANG_$(LANG) @@ -40,7 +40,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lmxml -lbba -ltinysmb -lfat -lz -logc -lm -lfreetype +LIBS := -lpng -lmxml -lbba -ltinysmb -lfat -lz -logc -lm -lfreetype #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/Makefile.wii b/Makefile.wii index 874ade77..82be63fd 100644 --- a/Makefile.wii +++ b/Makefile.wii @@ -21,7 +21,7 @@ BUILD := build_wii SOURCES := source/fceultra source/fceultra/boards \ source/fceultra/drivers/common source/fceultra/input \ source/fceultra/mappers source/fceultra/mbshare \ - source/ngc source/sz + source/ngc DATA := data INCLUDES := source/fceultra source/ngc LANG := ENGLISH # Supported languages: ENGLISH @@ -29,7 +29,7 @@ LANG := ENGLISH # Supported languages: ENGLISH #--------------------------------------------------------------------------------- # options for code generation #--------------------------------------------------------------------------------- -CFLAGS = -g -O3 -Wall $(MACHDEP) $(INCLUDE) -DNGC -DWII_DVD \ +CFLAGS = -g -O2 -Wall $(MACHDEP) $(INCLUDE) -DNGC -DWII_DVD \ -DHAVE_ASPRINTF -DSTDC -DFCEU_VERSION_NUMERIC=9812 \ -D_SZ_ONE_DIRECTORY -D_LZMA_IN_CB -D_LZMA_OUT_READ \ -DLANG_$(LANG) @@ -40,7 +40,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map -Wl,--cref #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -ldi -lmxml -lfat -lwiiuse -lz -lbte -logc -lm -lfreetype -ltinysmb +LIBS := -ldi -lpng -lmxml -lfat -lwiiuse -lz -lbte -logc -lm -lfreetype -ltinysmb #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/readme.txt b/readme.txt index bd8e4771..39a6de17 100644 --- a/readme.txt +++ b/readme.txt @@ -1,26 +1,27 @@ ¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - FCE Ultra GX - - Version 2.0.4 - http://code.google.com/p/fceugc + Version 2.0.3 (Under GPL License) ¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ - + +-=[ Explanation ]=- + FCE Ultra GX is a modified port of the FCE Ultra 0.98.12 Nintendo Entertainment system for x86 (Windows/Linux) PC's. With it you can play NES games on your Wii/GameCube. Version 2 is a complete rewrite based on code from the -SNES9x GX project. +SNES9x GX and Genesis Plus GX projects. -=[ Features ]=- * Wiimote, Nunchuk, Classic, and Gamecube controller support * iNES, FDS, VS, UNIF, and NSF ROM support -* 1-4 Player Support +* 1-2 Player Support * Zapper support * RAM and State saving * Custom controller configurations -* SD, USB, DVD, SMB, GC Memory Card, Zip, and 7z support +* SD, USB, DVD, SMB, GC Memory Card, and Zip support * NES Compatibility Based on v0.98.12 * Sound Filters * Graphics Filters (GX Chipset, Cheesy and 2x) @@ -29,17 +30,6 @@ SNES9x GX project. |0O×øo· UPDATE HISTORY ·oø×O0| `¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' -[What's New 2.0.4 - October 15, 2008] -* Wii DVD fixed -* FDS BIOS loading works now -* FDS disk switching now consistently works with one button press -* FDS saving implemented -* 7z support -* Faster SD/USB (readahead cache enabled) -* VS coin now mapped to 1 button for VS zapper games -* Changed GC controller mappings - Select - Z, Start - Start, - Home - Start+A, Special - L - [What's New 2.0.3 - October 1, 2008] * Complete rewrite of loading code - FDS / UNIF / NSF support added! * VS games work (coin insert submitted by pakitovic) @@ -175,6 +165,59 @@ Palette - The colors used while viewing the game: zaphod-smb . vs-drmar . vs-cv . vs-smb Timing - NTSC or PAL (Depends if you're running a PAL or NTSC game) + +×—–­—–­—–­—–­ –­—–­—–­—–­—–­—–­—–­—–­—–­—–­— ­—–­—–­—–­—–­—–­—–­—–­—-­—–­-–•¬ +|0O×øo· UPDATE HISTORY (1.0.x) ·oø×O0| +`¨•¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨¨ ¨¨¨¨¨¨¨¨¨¨¨¨¨' + +What's new [20080331] + ++[Askot] +- Fixed/changed SDCARD slot selection for searching roms, at + start you will be prompted for this option. +- Code cleanup. + ++[dsbomb] +- Added Wii mode support. +- Give a "Bad cartridge" error instead of locking up. +- Joystick fixes due to libogc r14's changed stick values +- Rearranged menu to make more sense, and consistent with Snes9x +- Add "Reboot" menu option +- Removed "." directory from SD card listing, it's pointless +- Expand DVD reading to DVD9 size (once DVDs are working again) +- Added option to go back a menu by pressing B. + +What's new? Askot [20080326] +- Added saving state in SD Card (State files will be saved in root of SDCARD). + *Note: I can't make it work to save in root:\fceu\saves, so help needed. +- Added SDCARD slot selection for searching roms, meaning, you can search roms + from SDCARD SLOT A & SLOT B (Beta, meaning, buggy, but works). +- For standarization, you must create folders root:\fceu\roms to read NES + roms files from SDCARD. +- Added C-Left to call Menu. +- Reading files from SD Card it's faster, now they're called from cache + after first reading. +- Menu in saving STATE file changed to choose SLOT, DEVICE, Save STATE, + Load STATE, Return to previous. +- Added option PSO/SD Reload to menu, still works (START+B+X) +- Modified controls when going into the rom selection menu (DVD or + SDCARD): + + Use B to quit selection list. + + Use L/R triggrers or Pad Left/Right to go down/up one full page. +- Some menu rearrangment and a little of sourcecode cleanup: + + Everytime you pressed B button on any option, playgame started, not anymore + until you select Play Game option. + +What's new? asako [20070831] +- modify mmc3 code for Chinese pirated rom +- add some Chinese pirated rom mappers + +What's new? _svpe_ [20070607] +- Wii support (PAL50 fix, 1.35GiB restriction removed) +- 7zip ROM loading support from the DVD (not from a SD card!!) +- dvd_read fix (the read data was always copied to readbuffer instead of *dst) +- slower file selection when using the D-Pad (I didn't like the selection to go +as fast as in the latest release) ¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤°`°¤ø,¸,ø¤°`°¤ø,¸¸,ø¤ diff --git a/source/fceultra/state.c b/source/fceultra/state.c index b225ab42..619bf0b1 100644 --- a/source/fceultra/state.c +++ b/source/fceultra/state.c @@ -41,8 +41,8 @@ #include "video.h" -void (*SPreSave)(void); -void (*SPostSave)(void); +static void (*SPreSave)(void); +static void (*SPostSave)(void); static int SaveStateStatus[10]; static int StateShow; @@ -113,15 +113,15 @@ static int SubWrite(FILE *st, SFORMAT *sf) if(sf->s&RLSB) FlipByteOrder(sf->v,sf->s&(~RLSB)); #endif - + fwrite((uint8 *)sf->v,1,sf->s&(~RLSB),st); /* Now restore the original byte order. */ #ifndef LSB_FIRST - if(sf->s&RLSB) + if(sf->s&RLSB) FlipByteOrder(sf->v,sf->s&(~RLSB)); #endif } - sf++; + sf++; } return(acc); @@ -132,9 +132,9 @@ static int WriteStateChunk(FILE *st, int type, SFORMAT *sf) int bsize; fputc(type,st); - + bsize=SubWrite(0,sf); - write32le(bsize,st); + write32le(bsize,st); if(!SubWrite(st,sf)) return(0); return (bsize+5); @@ -235,11 +235,11 @@ int FCEUSS_SaveFP(FILE *st) { static uint32 totalsize; static uint8 header[16]="FCS"; - + memset(header+4,0,13); header[3]=0xFF; FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC); - fwrite(header,1,16,st); + fwrite(header,1,16,st); FCEUPPU_SaveState(); FCEUSND_SaveState(); totalsize=WriteStateChunk(st,1,SFCPU); @@ -305,12 +305,12 @@ int FCEUSS_LoadFP(FILE *st) x=ReadStateChunks(st,*(uint32*)(header+4)); if(stateversion<9500) X.IRQlow=0; - + if(GameStateRestore) GameStateRestore(stateversion); if(x) { FCEUPPU_LoadState(stateversion); - FCEUSND_LoadState(stateversion); + FCEUSND_LoadState(stateversion); } return(x); } @@ -348,7 +348,7 @@ int FCEUSS_Load(char *fname) SaveStateStatus[CurrentState]=1; fclose(st); return(1); - } + } else { SaveStateStatus[CurrentState]=1; @@ -418,7 +418,7 @@ void FCEUI_SelectState(int w) CurrentState=w; StateShow=180; FCEU_DispMessage("-select state-"); -} +} void FCEUI_SaveState(char *fname) { @@ -448,7 +448,7 @@ void FCEUI_LoadState(char *fname) if(FCEUSS_SaveFP(fp)) { fclose(fp); - FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn); + FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn); } else fclose(fp); /*** REMOVED GC V1.0 diff --git a/source/ngc/dvd.c b/source/ngc/dvd.c index 05f0b19f..bcde09f8 100644 --- a/source/ngc/dvd.c +++ b/source/ngc/dvd.c @@ -14,7 +14,6 @@ #include #include #include -#include #ifdef WII_DVD #include @@ -22,204 +21,72 @@ #include "menudraw.h" #include "gcunzip.h" -#include "fceuconfig.h" -u64 dvddir = 0; // offset of currently selected file or folder -int dvddirlength = 0; // length of currently selected file or folder -u64 dvdrootdir = 0; // offset of DVD root -bool isWii = false; +u64 dvddir = 0; +u64 dvdrootdir = 0; +int dvddirlength = 0; #ifdef HW_DOL /** DVD I/O Address base **/ volatile unsigned long *dvd = (volatile unsigned long *) 0xCC006000; #endif -/**************************************************************************** - * dvd_read - * - * Main DVD function, everything else uses this! - * returns: 1 - ok ; 0 - error - ***************************************************************************/ -#define ALIGN_FORWARD(x,align) ((typeof(x))((((uint32_t)(x)) + (align) - 1) & (~(align-1)))) -#define ALIGN_BACKWARD(x,align) ((typeof(x))(((uint32_t)(x)) & (~(align-1)))) + /** Due to lack of memory, we'll use this little 2k keyhole for all DVD operations **/ +unsigned char DVDreadbuffer[2048] ATTRIBUTE_ALIGN (32); +unsigned char dvdbuffer[2048]; + + /** + * dvd_read + * + * The only DVD function we need - you gotta luv gc-linux self-boots! + * returns: 1 - ok ; 0 - error + */ int dvd_read (void *dst, unsigned int len, u64 offset) { + + unsigned char *buffer = (unsigned char *) (unsigned int) DVDreadbuffer; + if (len > 2048) return 0; /*** We only allow 2k reads **/ - // don't read past the end of the DVD (1.5 GB for GC DVD, 4.7 GB for DVD) - if((offset < 0x57057C00) || (isWii && (offset < 0x118244F00LL))) + DCInvalidateRange ((void *) buffer, len); + + if(offset < 0x57057C00 || (isWii == true && offset < 0x118244F00LL)) // don't read past the end of the DVD { - u8 * buffer = (u8 *)memalign(32, 0x8000); - u32 off_size = 0; - DCInvalidateRange ((void *) buffer, len); + #ifdef HW_DOL - #ifdef HW_DOL - dvd[0] = 0x2E; - dvd[1] = 0; - dvd[2] = 0xA8000000; - dvd[3] = (u32)(offset >> 2); - dvd[4] = len; - dvd[5] = (u32) buffer; - dvd[6] = len; - dvd[7] = 3; - - // Enable reading with DMA - while (dvd[7] & 1); - - // Ensure it has completed - if (dvd[0] & 0x4) - return 0; - #else - off_size = offset - ALIGN_BACKWARD(offset,0x800); - if (DI_ReadDVD( - buffer, - (ALIGN_FORWARD(offset + len,0x800) - ALIGN_BACKWARD(offset,0x800)) >> 11, - (u32)(ALIGN_BACKWARD(offset, 0x800) >> 11) - )) - return 0; - #endif + dvd[0] = 0x2E; + dvd[1] = 0; + dvd[2] = 0xA8000000; + dvd[3] = (u32)(offset >> 2); + dvd[4] = len; + dvd[5] = (u32) buffer; + dvd[6] = len; + dvd[7] = 3; /*** Enable reading with DMA ***/ + while (dvd[7] & 1); + memcpy (dst, buffer, len); + + if (dvd[0] & 0x4) /* Ensure it has completed */ + return 0; - memcpy (dst, buffer+off_size, len); - free(buffer); return 1; + + #elif WII_DVD + int ret = 1; + ret = DI_ReadDVD(dst, len >> 11, (u32)(offset >> 11)); + if (ret==0) + return 1; + else + return 0; + #endif } return 0; } -/**************************************************************************** - * dvd_buffered_read - * - * the GC's dvd drive only supports offsets and length which are a multiple - * of 32 bytes additionally the max length of a read is 2048 bytes - * this function removes these limitations - * additionally the 7zip SDK does often read data in 1 byte parts from the - * DVD even when it could read 32 bytes. the dvdsf_buffer has been added to - * avoid having to read the same sector over and over again - ***************************************************************************/ - -#define DVD_LENGTH_MULTIPLY 32 -#define DVD_OFFSET_MULTIPLY 32 -#define DVD_MAX_READ_LENGTH 2048 -#define DVD_SECTOR_SIZE 2048 - -unsigned char dvdsf_buffer[DVD_SECTOR_SIZE]; -u64 dvdsf_last_offset = 0; -u64 dvdsf_last_length = 0; - -int dvd_buffered_read(void *dst, u32 len, u64 offset) -{ - int ret = 0; - - // only read data if the data inside dvdsf_buffer cannot be used - if(offset != dvdsf_last_offset || len > dvdsf_last_length) - { - memset(&dvdsf_buffer, '\0', DVD_SECTOR_SIZE); - ret = dvd_read(&dvdsf_buffer, len, offset); - dvdsf_last_offset = offset; - dvdsf_last_length = len; - } - - memcpy(dst, &dvdsf_buffer, len); - return ret; -} - -int dvd_safe_read(void *dst_v, u32 len, u64 offset) -{ - unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector - - // if read size and length are a multiply of DVD_(OFFSET,LENGTH)_MULTIPLY and length < DVD_MAX_READ_LENGTH - // we don't need to fix anything - if(len % DVD_LENGTH_MULTIPLY == 0 && offset % DVD_OFFSET_MULTIPLY == 0 && len <= DVD_MAX_READ_LENGTH) - { - int ret = dvd_buffered_read(buffer, len, offset); - memcpy(dst_v, &buffer, len); - return ret; - } - else - { - // no errors yet -> ret = 0 - // the return value of dvd_read will be OR'd with ret - // because dvd_read does return 1 on error and 0 on success and - // because 0 | 1 = 1 ret will also contain 1 if at least one error - // occured and 0 otherwise ;) - int ret = 0; // return value of dvd_read - - // we might need to fix all 3 issues - unsigned char *dst = (unsigned char *)dst_v; // gcc will not allow to use var[num] on void* types - u64 bytesToRead; // the number of bytes we still need to read & copy to the output buffer - u64 currentOffset; // the current dvd offset - u64 bufferOffset; // the current buffer offset - u64 i, j, k; // temporary variables which might be used for different stuff - // unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector - - currentOffset = offset; - bytesToRead = len; - bufferOffset = 0; - - // fix first issue (offset is not a multiply of 32) - if(offset % DVD_OFFSET_MULTIPLY) - { - // calculate offset of the prior 32 byte position - i = currentOffset - (currentOffset % DVD_OFFSET_MULTIPLY); - - // calculate the offset from which the data of the dvd buffer will be copied - j = currentOffset % DVD_OFFSET_MULTIPLY; - - // calculate the number of bytes needed to reach the next DVD_OFFSET_MULTIPLY byte mark - k = DVD_OFFSET_MULTIPLY - j; - - // maybe we'll only need to copy a few bytes and we therefore don't even reach the next sector - if(k > len) - { - k = len; - } - - // read 32 bytes from the last 32 byte position - ret |= dvd_buffered_read(buffer, DVD_OFFSET_MULTIPLY, i); - - // copy the bytes to the output buffer and update currentOffset, bufferOffset and bytesToRead - memcpy(&dst[bufferOffset], &buffer[j], k); - currentOffset += k; - bufferOffset += k; - bytesToRead -= k; - } - - // fix second issue (more than 2048 bytes are needed) - if(bytesToRead > DVD_MAX_READ_LENGTH) - { - // calculate the number of 2048 bytes sector needed to get all data - i = (bytesToRead - (bytesToRead % DVD_MAX_READ_LENGTH)) / DVD_MAX_READ_LENGTH; - - // read data in 2048 byte sector - for(j = 0; j < i; j++) - { - ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read sector - memcpy(&dst[bufferOffset], buffer, DVD_MAX_READ_LENGTH); // copy to output buffer - - // update currentOffset, bufferOffset and bytesToRead - currentOffset += DVD_MAX_READ_LENGTH; - bufferOffset += DVD_MAX_READ_LENGTH; - bytesToRead -= DVD_MAX_READ_LENGTH; - } - } - - // fix third issue (length is not a multiply of 32) - if(bytesToRead) - { - ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read 32 byte from the dvd - memcpy(&dst[bufferOffset], buffer, bytesToRead); // copy bytes to output buffer - } - - //free(tmp); - return ret; - } -} - /** Minimal ISO Directory Definition **/ #define RECLEN 0 /* Record length */ #define EXTENT 6 /* Extent */ @@ -232,18 +99,17 @@ int dvd_safe_read(void *dst_v, u32 len, u64 offset) #define PVDROOT 0x9c static int IsJoliet = 0; -/**************************************************************************** +/** * Primary Volume Descriptor * * The PVD should reside between sector 16 and 31. * This is for single session DVD only. - ***************************************************************************/ + */ int getpvd () { int sector = 16; u32 rootdir32; - unsigned char dvdbuffer[2048]; dvddir = dvddirlength = 0; IsJoliet = -1; @@ -301,7 +167,7 @@ getpvd () * TestDVD() * * Tests if a ISO9660 DVD is inserted and available - ***************************************************************************/ + ****************************************************************************/ bool TestDVD() { @@ -320,15 +186,15 @@ bool TestDVD() return true; } -/**************************************************************************** +/** * getentry * * Support function to return the next file entry, if any * Declared static to avoid accidental external entry. - ***************************************************************************/ + */ static int diroffset = 0; static int -getentry (int entrycount, unsigned char dvdbuffer[]) +getentry (int entrycount) { char fname[512]; /* Huge, but experience has determined this */ char *ptr; @@ -431,7 +297,7 @@ getentry (int entrycount, unsigned char dvdbuffer[]) return 0; } -/**************************************************************************** +/** * parseDVDdirectory * * This function will parse the directory tree. @@ -439,7 +305,7 @@ getentry (int entrycount, unsigned char dvdbuffer[]) * getpvd, a previous parse or a menu selection. * * The return value is number of files collected, or 0 on failure. - ***************************************************************************/ + */ int ParseDVDdirectory () { @@ -448,7 +314,6 @@ ParseDVDdirectory () u64 rdoffset; int len = 0; int filecount = 0; - unsigned char dvdbuffer[2048]; // initialize selection selection = offset = 0; @@ -468,7 +333,7 @@ ParseDVDdirectory () diroffset = 0; - while (getentry (filecount, dvdbuffer)) + while (getentry (filecount)) { if(strlen(filelist[filecount].filename) > 0 && filecount < MAXFILES) filecount++; @@ -484,12 +349,12 @@ ParseDVDdirectory () return filecount; } -/**************************************************************************** - * DirectorySearch - * - * Searches for the directory name specified within the current directory - * Returns the index of the directory, or -1 if not found - ***************************************************************************/ +/** +* DirectorySearch +* +* Searches for the directory name specified within the current directory +* Returns the index of the directory, or -1 if not found +*/ int DirectorySearch(char dir[512]) { int i; @@ -499,14 +364,14 @@ int DirectorySearch(char dir[512]) return -1; } -/**************************************************************************** - * SwitchDVDFolder - * - * Recursively searches for any directory path 'dir' specified - * Also loads the directory contents via ParseDVDdirectory() - * It relies on dvddir, dvddirlength, and filelist being pre-populated - ***************************************************************************/ -bool SwitchDVDFolderR(char * dir, int maxDepth) +/** +* SwitchDVDFolder +* +* Recursively searches for any directory path 'dir' specified +* Also loads the directory contents via ParseDVDdirectory() +* It relies on dvddir, dvddirlength, and filelist being pre-populated +*/ +bool DoSwitchDVDFolder(char * dir, int maxDepth) { if(maxDepth > 8) // only search to a max depth of 8 levels return false; @@ -533,7 +398,7 @@ bool SwitchDVDFolderR(char * dir, int maxDepth) if(lastdir) return true; else - return SwitchDVDFolderR(nextdir, maxDepth++); + return DoSwitchDVDFolder(nextdir, maxDepth++); } return false; } @@ -553,20 +418,20 @@ bool SwitchDVDFolder(char origdir[]) if(dir[strlen(dir)-1] == '/') dir[strlen(dir)-1] = 0; - return SwitchDVDFolderR(dirptr, 0); + return DoSwitchDVDFolder(dirptr, 0); } /**************************************************************************** * LoadDVDFile - * This function will load a file from DVD + * This function will load a file from DVD, in BIN, SMD or ZIP format. * The values for offset and length are inherited from dvddir and * dvddirlength. * - * The buffer parameter should re-use the initial ROM buffer - ***************************************************************************/ + * The buffer parameter should re-use the initial ROM buffer. + ****************************************************************************/ int -LoadDVDFile (unsigned char *buffer, int length) +LoadDVDFile (unsigned char *buffer) { int offset; int blocks; @@ -574,44 +439,41 @@ LoadDVDFile (unsigned char *buffer, int length) u64 discoffset; char readbuffer[2048]; - dvddir = filelist[selection].offset; - dvddirlength = filelist[selection].length; - // How many 2k blocks to read blocks = dvddirlength / 2048; offset = 0; discoffset = dvddir; ShowAction ((char*) "Loading..."); + dvd_read (readbuffer, 2048, discoffset); - if(length > 0) // do a partial read (eg: to check file header) + int r = IsZipFile (readbuffer); + + if(r == 2) // 7z { - dvd_read (buffer, length, discoffset); + WaitPrompt ((char *)"7z files are not supported!"); + return 0; } - else // load whole file - { - dvd_read (readbuffer, 2048, discoffset); - if (IsZipFile (readbuffer)) + if (r) + { + return UnZipDVDFile (buffer, discoffset); // unzip from dvd + } + else + { + for (i = 0; i < blocks; i++) { - return UnZipBuffer (buffer, METHOD_DVD); // unzip from dvd + dvd_read (readbuffer, 2048, discoffset); + memcpy (buffer + offset, readbuffer, 2048); + offset += 2048; + discoffset += 2048; } - else - { - for (i = 0; i < blocks; i++) - { - dvd_read (readbuffer, 2048, discoffset); - memcpy (buffer + offset, readbuffer, 2048); - offset += 2048; - discoffset += 2048; - } - /*** And final cleanup ***/ - if (dvddirlength % 2048) - { - i = dvddirlength % 2048; - dvd_read (readbuffer, 2048, discoffset); - memcpy (buffer + offset, readbuffer, i); - } + /*** And final cleanup ***/ + if (dvddirlength % 2048) + { + i = dvddirlength % 2048; + dvd_read (readbuffer, 2048, discoffset); + memcpy (buffer + offset, readbuffer, i); } } return dvddirlength; @@ -625,7 +487,7 @@ LoadDVDFile (unsigned char *buffer, int length) * memcard interface. * * libOGC tends to foul up if you don't, and sometimes does if you do! - ***************************************************************************/ + ****************************************************************************/ #ifdef HW_DOL void uselessinquiry () { @@ -641,11 +503,7 @@ void uselessinquiry () while (dvd[7] & 1); } -/**************************************************************************** - * dvd_motor_off( ) - * Turns off DVD drive motor so it doesn't make noise (Gamecube only) - ***************************************************************************/ -void dvd_motor_off () +void dvd_motor_off( ) { dvd[0] = 0x2e; dvd[1] = 0; @@ -662,11 +520,11 @@ void dvd_motor_off () dvd[1] = 0; } -/**************************************************************************** - * dvd_driveid - * - * Gets and returns the dvd driveid - ***************************************************************************/ +/** + * dvd_driveid + * + * Gets and returns the dvd driveid +**/ int dvd_driveid() { @@ -690,20 +548,3 @@ int dvd_driveid() #endif -/**************************************************************************** - * SetDVDDriveType() - * - * Sets the DVD drive ID for use to determine disc size (1.5 GB or 4.7 GB) - ***************************************************************************/ -void SetDVDDriveType() -{ - #ifdef HW_RVL - isWii = true; - #else - int drvid = dvd_driveid (); - if ( drvid == 4 || drvid == 6 || drvid == 8 ) - isWii = false; - else - isWii = true; - #endif -} diff --git a/source/ngc/dvd.h b/source/ngc/dvd.h index 2eb6bb48..20d52a29 100644 --- a/source/ngc/dvd.h +++ b/source/ngc/dvd.h @@ -14,16 +14,9 @@ int getpvd (); int ParseDVDdirectory (); -int LoadDVDFile (unsigned char *buffer, int length); +int LoadDVDFile (unsigned char *buffer); bool TestDVD(); int dvd_read (void *dst, unsigned int len, u64 offset); -int dvd_safe_read (void *dst, unsigned int len, u64 offset); bool SwitchDVDFolder(char dir[]); -#ifdef HW_DOL -void dvd_motor_off (); -#endif - -extern u64 dvddir; -extern int dvddirlength; #endif diff --git a/source/ngc/fceuconfig.h b/source/ngc/fceuconfig.h index 720686d9..a010c197 100644 --- a/source/ngc/fceuconfig.h +++ b/source/ngc/fceuconfig.h @@ -15,8 +15,8 @@ void DefaultSettings (); -#define VERSIONNUM "2.0.4" -#define VERSIONSTR "FCE Ultra GX 2.0.4" +#define VERSIONNUM "2.0.3" +#define VERSIONSTR "FCE Ultra GX 2.0.3" #define NOTSILENT 0 #define SILENT 1 diff --git a/source/ngc/fceugc.c b/source/ngc/fceugc.c index 09efb314..88144329 100644 --- a/source/ngc/fceugc.c +++ b/source/ngc/fceugc.c @@ -72,13 +72,13 @@ int main(int argc, char *argv[]) } InitialiseSound(); - fatInit (8, false); + fatInitDefault(); #ifndef HW_RVL DVD_Init(); #endif // allocate memory to store rom - nesrom = (unsigned char *)malloc(1024*1024*3); // 3 MB should be plenty + nesrom = (unsigned char *)malloc(1024*1024*2); // 2 MB should be plenty /*** Minimal Emulation Loop ***/ if ( !FCEUI_Initialize() ) { diff --git a/source/ngc/fceuload.c b/source/ngc/fceuload.c index cce6c2d2..4f916ec9 100644 --- a/source/ngc/fceuload.c +++ b/source/ngc/fceuload.c @@ -128,7 +128,7 @@ int GCMemROM(int method, int size) break; case METHOD_SMB: sprintf(filepath, "%s/disksys.rom", GCSettings.LoadFolder); - biosSize = LoadBufferFromSMB(tmpbuffer, filepath, 0, NOTSILENT); + biosSize = LoadBufferFromSMB(tmpbuffer, filepath, NOTSILENT); break; } diff --git a/source/ngc/fceuram.c b/source/ngc/fceuram.c index 59fdd7a2..a05b74c9 100644 --- a/source/ngc/fceuram.c +++ b/source/ngc/fceuram.c @@ -71,13 +71,6 @@ int NGCFCEU_GameSave(CartInfo *LocalHWInfo, int operation) bool SaveRAM (int method, bool silent) { - if(nesGameType == 4) - { - if(!silent) - WaitPrompt((char *)"Saving is not available for FDS games!"); - return false; - } - ShowAction ((char*) "Saving..."); if(method == METHOD_AUTO) @@ -136,13 +129,6 @@ bool SaveRAM (int method, bool silent) bool LoadRAM (int method, bool silent) { - if(nesGameType == 4) - { - if(!silent) - WaitPrompt((char *)"Saving is not available for FDS games!"); - return false; - } - ShowAction ((char*) "Loading..."); if(method == METHOD_AUTO) diff --git a/source/ngc/fceustate.c b/source/ngc/fceustate.c index 170d9889..f692ef20 100644 --- a/source/ngc/fceustate.c +++ b/source/ngc/fceustate.c @@ -221,9 +221,6 @@ int GCSaveChunk(int chunkid, SFORMAT *sf) { * It uses memory for it's I/O and has an added CHNK block. * The file is terminated with CHNK length of 0. ****************************************************************************/ -extern void (*SPreSave)(void); -extern void (*SPostSave)(void); - int GCFCEUSS_Save() { int totalsize = 0; @@ -247,7 +244,6 @@ int GCFCEUSS_Save() /*** And Comments ***/ strncpy (Comment[1],romFilename,31); // we only have 32 chars to work with! - Comment[1][31] = 0; memfwrite(&Comment[0], 64); totalsize += 64; @@ -259,15 +255,8 @@ int GCFCEUSS_Save() totalsize += GCSaveChunk(3, FCEUPPU_STATEINFO); totalsize += GCSaveChunk(4, FCEUCTRL_STATEINFO); totalsize += GCSaveChunk(5, FCEUSND_STATEINFO); - - if(nesGameType == 4) // FDS - SPreSave(); - totalsize += GCSaveChunk(0x10, SFMDATA); - if(nesGameType == 4) // FDS - SPostSave(); - /*** Add terminating CHNK ***/ memfwrite(&chunk,4); memfwrite(&zero,4); diff --git a/source/ngc/fileop.c b/source/ngc/fileop.c index 42ce9baa..1edf08a0 100644 --- a/source/ngc/fileop.c +++ b/source/ngc/fileop.c @@ -23,8 +23,7 @@ #include "menudraw.h" #include "filesel.h" -// FAT file pointer - the only one we should ever use! -FILE * fatfile; +FILE * filehandle; /**************************************************************************** * fat_is_mounted @@ -60,7 +59,6 @@ bool ChangeFATInterface(int method, bool silent) { devFound = true; fatSetDefaultInterface(PI_INTERNAL_SD); - fatEnableReadAhead (PI_INTERNAL_SD, 6, 64); } #endif @@ -87,7 +85,6 @@ bool ChangeFATInterface(int method, bool silent) { devFound = true; fatSetDefaultInterface(PI_USBSTORAGE); - fatEnableReadAhead (PI_USBSTORAGE, 6, 64); } else { @@ -148,7 +145,6 @@ ParseFATdirectory(int method) strncpy(filelist[nbfiles].displayname, filename, MAXDISPLAY+1); // crop name for display filelist[nbfiles].length = filestat.st_size; filelist[nbfiles].flags = (filestat.st_mode & _IFDIR) == 0 ? 0 : 1; // flag this as a dir - filelist[nbfiles].offset = 0; nbfiles++; } } @@ -164,49 +160,51 @@ ParseFATdirectory(int method) /**************************************************************************** * LoadFATFile - * length > 0 - partial file read (starting from start) - * length = 0 - full read - ***************************************************************************/ + ****************************************************************************/ int -LoadFATFile (char * rbuffer, int length) +LoadFATFile () { char zipbuffer[2048]; char filepath[MAXPATHLEN]; + FILE *handle; u32 size; - if (!MakeROMPath(filepath, METHOD_SD)) + /* Check filename length */ + if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) + sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename); + else { WaitPrompt((char*) "Maximum filepath length reached!"); return -1; } - fatfile = fopen (filepath, "rb"); - if (fatfile > 0) + handle = fopen (filepath, "rb"); + if (handle > 0) { - if(length > 0) // do a partial read (eg: to check file header) + fread (zipbuffer, 1, 2048, handle); + + int r = IsZipFile (zipbuffer); + + if(r == 2) // 7z { - fread (rbuffer, 1, length, fatfile); - size = length; + WaitPrompt ((char *)"7z files are not supported!"); + return 0; } - else // load whole file + + if (r) { - fread (zipbuffer, 1, 2048, fatfile); - - if (IsZipFile (zipbuffer)) - { - size = UnZipBuffer ((unsigned char *)rbuffer, METHOD_SD); // unzip from FAT - } - else - { - // Just load the file up - fseek(fatfile, 0, SEEK_END); - size = ftell(fatfile); // get filesize - fseek(fatfile, 2048, SEEK_SET); // seek back to point where we left off - memcpy (rbuffer, zipbuffer, 2048); // copy what we already read - fread (rbuffer + 2048, 1, size - 2048, fatfile); - } + size = UnZipFATFile (nesrom, handle); // unzip from FAT } - fclose (fatfile); + else + { + // Just load the file up + fseek(handle, 0, SEEK_END); + size = ftell(handle); // get filesize + fseek(handle, 2048, SEEK_SET); // seek back to point where we left off + memcpy (nesrom, zipbuffer, 2048); // copy what we already read + fread (nesrom + 2048, 1, size - 2048, handle); + } + fclose (handle); return size; } else @@ -214,29 +212,8 @@ LoadFATFile (char * rbuffer, int length) WaitPrompt((char*) "Error opening file"); return 0; } -} -/**************************************************************************** - * LoadFATSzFile - * Loads the selected file # from the specified 7z into rbuffer - * Returns file size - ***************************************************************************/ -int -LoadFATSzFile(char * filepath, unsigned char * rbuffer) -{ - u32 size; - fatfile = fopen (filepath, "rb"); - if (fatfile > 0) - { - size = SzExtractFile(filelist[selection].offset, rbuffer); - fclose (fatfile); - return size; - } - else - { - WaitPrompt((char*) "Error opening file"); - return 0; - } + return 0; } /**************************************************************************** @@ -253,11 +230,12 @@ LoadSaveBufferFromFAT (char *filepath, bool silent) int LoadBufferFromFAT (char * sbuffer, char *filepath, bool silent) { + FILE *handle; int size = 0; - fatfile = fopen (filepath, "rb"); + handle = fopen (filepath, "rb"); - if (fatfile <= 0) + if (handle <= 0) { if ( !silent ) { @@ -269,11 +247,11 @@ LoadBufferFromFAT (char * sbuffer, char *filepath, bool silent) } // Just load the file up - fseek(fatfile, 0, SEEK_END); // go to end of file - size = ftell(fatfile); // get filesize - fseek(fatfile, 0, SEEK_SET); // go to start of file - fread (sbuffer, 1, size, fatfile); - fclose (fatfile); + fseek(handle, 0, SEEK_END); // go to end of file + size = ftell(handle); // get filesize + fseek(handle, 0, SEEK_SET); // go to start of file + fread (sbuffer, 1, size, handle); + fclose (handle); return size; } @@ -284,11 +262,13 @@ LoadBufferFromFAT (char * sbuffer, char *filepath, bool silent) int SaveBufferToFAT (char *filepath, int datasize, bool silent) { + FILE *handle; + if (datasize) { - fatfile = fopen (filepath, "wb"); + handle = fopen (filepath, "wb"); - if (fatfile <= 0) + if (handle <= 0) { char msg[100]; sprintf(msg, "Couldn't save %s", filepath); @@ -296,8 +276,8 @@ SaveBufferToFAT (char *filepath, int datasize, bool silent) return 0; } - fwrite (savebuffer, 1, datasize, fatfile); - fclose (fatfile); + fwrite (savebuffer, 1, datasize, handle); + fclose (handle); } return datasize; } diff --git a/source/ngc/fileop.h b/source/ngc/fileop.h index 754fa58d..d4417b15 100644 --- a/source/ngc/fileop.h +++ b/source/ngc/fileop.h @@ -24,13 +24,11 @@ bool ChangeFATInterface(int method, bool silent); int ParseFATdirectory(int method); -int LoadFATFile (char * fbuffer, int length); -int LoadFATSzFile(char * filepath, unsigned char * rbuffer); +int LoadFATFile (); int SaveBufferToFAT (char *filepath, int datasize, bool silent); int LoadSaveBufferFromFAT (char *filepath, bool silent); int LoadBufferFromFAT (char * buffer, char *filepath, bool silent); extern char currFATdir[MAXPATHLEN]; -extern FILE * fatfile; #endif diff --git a/source/ngc/filesel.c b/source/ngc/filesel.c index f06cf5b8..afa788f7 100644 --- a/source/ngc/filesel.c +++ b/source/ngc/filesel.c @@ -29,20 +29,20 @@ #include "memcardop.h" #include "pad.h" #include "fceuload.h" -#include "gcunzip.h" int offset; int selection; char currentdir[MAXPATHLEN]; -char szpath[MAXPATHLEN]; char romFilename[200]; int nesGameType; int maxfiles; extern int screenheight; +extern u64 dvddir; +extern int dvddirlength; + // Global file entry table FILEENTRIES filelist[MAXFILES]; -bool inSz = false; unsigned char savebuffer[SAVEBUFFERSIZE]; @@ -163,28 +163,6 @@ int UpdateDirName(int method) } } -bool MakeROMPath(char filepath[], int method) -{ - char temppath[MAXPATHLEN]; - - // Check filename length - if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) - { - sprintf(temppath, "%s/%s",currentdir,filelist[selection].filename); - - if(method == METHOD_SMB) - strcpy(filepath, SMBPath(temppath)); - else - strcpy(filepath, temppath); - return true; - } - else - { - filepath[0] = 0; - return false; - } -} - /*************************************************************************** * FileSortCallback * @@ -212,83 +190,6 @@ int FileSortCallback(const void *f1, const void *f2) return stricmp(((FILEENTRIES *)f1)->filename, ((FILEENTRIES *)f2)->filename); } -/**************************************************************************** - * IsValidROM - * - * Checks if the specified file is a valid ROM - * For now we will just check the file extension and file size - * If the file is a zip, we will check the file extension / file size of the - * first file inside - ***************************************************************************/ - -bool IsValidROM(int method) -{ - // file size should be between 10K and 3MB - if(filelist[selection].length < (1024*10) || - filelist[selection].length > (1024*1024*3)) - { - WaitPrompt((char *)"Invalid file size!"); - return false; - } - - if (strlen(filelist[selection].filename) > 4) - { - char * p = strrchr(filelist[selection].filename, '.'); - - if (p != NULL) - { - if(stricmp(p, ".zip") == 0 && !inSz) - { - // we need to check the file extension of the first file in the archive - char * zippedFilename = GetFirstZipFilename (method); - - if(zippedFilename == NULL) // we don't want to run strlen on NULL - p = NULL; - else if(strlen(zippedFilename) > 4) - p = strrchr(zippedFilename, '.'); - else - p = NULL; - } - - if(p != NULL) - { - if ( - stricmp(p, ".nes") == 0 || - stricmp(p, ".fds") == 0 || - stricmp(p, ".nsf") == 0 || - stricmp(p, ".unf") == 0 || - stricmp(p, ".nez") == 0 || - stricmp(p, ".unif") == 0 - ) - { - return true; - } - } - } - } - WaitPrompt((char *)"Unknown file type!"); - return false; -} - -/**************************************************************************** - * IsSz - * - * Checks if the specified file is a 7z - ***************************************************************************/ - -bool IsSz() -{ - if (strlen(filelist[selection].filename) > 4) - { - char * p = strrchr(filelist[selection].filename, '.'); - - if (p != NULL) - if(stricmp(p, ".7z") == 0) - return true; - } - return false; -} - /**************************************************************************** * StripExt * @@ -360,30 +261,10 @@ int FileSelector (int method) { if ( selectit ) selectit = 0; - if (filelist[selection].flags) // This is directory { /* update current directory and set new entry list if directory has changed */ - - int status; - - if(inSz && selection == 0) // inside a 7z, requesting to leave - { - if(method == METHOD_DVD) - { - // go to directory the 7z was in - dvddir = filelist[0].offset; - dvddirlength = filelist[0].length; - } - inSz = false; - status = 1; - SzClose(); - } - else - { - status = UpdateDirName(method); - } - + int status = UpdateDirName(method); if (status == 1) // ok, open directory { switch (method) @@ -413,77 +294,44 @@ int FileSelector (int method) haverom = 1; // quit menu } } - else // this is a file + else // this is a file { - // 7z file - let's open it up to select a file inside - if(IsSz()) - { - // we'll store the 7z filepath for extraction later - if(!MakeROMPath(szpath, method)) - { - WaitPrompt((char*) "Maximum filepath length reached!"); - return -1; - } - int szfiles = SzParse(szpath, method); - if(szfiles) - { - maxfiles = szfiles; - inSz = true; - } - else - WaitPrompt((char*) "Error opening archive!"); - } - else - { - // check that this is a valid ROM - if(!IsValidROM(method)) - return 0; + // store the filename (w/o ext) - used for state saving + StripExt(romFilename, filelist[selection].filename); - // store the filename (w/o ext) - used for state saving - StripExt(romFilename, filelist[selection].filename); + ShowAction ((char *)"Loading..."); - ShowAction ((char *)"Loading..."); + int size = 0; - int size = 0; - - switch (method) - { - case METHOD_SD: - case METHOD_USB: - if(inSz) - size = LoadFATSzFile(szpath, nesrom); - else - size = LoadFATFile((char *)nesrom, 0); - break; - - case METHOD_DVD: - if(inSz) - size = SzExtractFile(filelist[selection].offset, nesrom); - else - size = LoadDVDFile(nesrom, 0); - break; - - case METHOD_SMB: - if(inSz) - size = LoadSMBSzFile(szpath, nesrom); - else - size = LoadSMBFile((char *)nesrom, 0); - break; - } - inSz = false; + switch (method) + { + case METHOD_SD: + case METHOD_USB: + size = LoadFATFile(); + break; + + case METHOD_DVD: + dvddir = filelist[selection].offset; + dvddirlength = filelist[selection].length; + size = LoadDVDFile(nesrom); + break; + + case METHOD_SMB: + size = LoadSMBFile(); + break; + } - if (size > 0) - { - if(GCMemROM(method, size) > 0) - return 1; - else - return 0; - } + if (size > 0) + { + if(GCMemROM(method, size) > 0) + return 1; else - { - WaitPrompt((char*) "Error loading ROM!"); return 0; - } + } + else + { + WaitPrompt((char*) "Error loading ROM!"); + return 0; } } redraw = 1; @@ -504,8 +352,7 @@ int FileSelector (int method) else if ( strcmp(filelist[1].filename,"..") == 0 ) { selection = selectit = 1; - } else - { + } else { return 0; } } // End of B diff --git a/source/ngc/filesel.h b/source/ngc/filesel.h index 7205807f..8b99e4ef 100644 --- a/source/ngc/filesel.h +++ b/source/ngc/filesel.h @@ -14,9 +14,9 @@ #include -#define SAVEBUFFERSIZE (512 * 1024) +#define SAVEBUFFERSIZE (64 * 1024) #define MAXJOLIET 255 -#define MAXDISPLAY 50 +#define MAXDISPLAY 54 typedef struct { @@ -39,7 +39,6 @@ extern char romFilename[]; extern int nesGameType; void ClearSaveBuffer (); -bool MakeROMPath(char filepath[], int method); int OpenROM (int method); int autoLoadMethod(); int autoSaveMethod(); diff --git a/source/ngc/gcunzip.c b/source/ngc/gcunzip.c index 95f8eb47..b1a29eda 100644 --- a/source/ngc/gcunzip.c +++ b/source/ngc/gcunzip.c @@ -14,15 +14,7 @@ #include #include #include - -#include "../sz/7zCrc.h" -#include "../sz/7zIn.h" -#include "../sz/7zExtract.h" - -#include "fceuconfig.h" #include "dvd.h" -#include "smbop.h" -#include "fileop.h" #include "menudraw.h" #include "gcunzip.h" @@ -64,6 +56,7 @@ FLIP16 (u16 b) * IsZipFile * * Returns 1 when Zip signature is found + * Returns 2 when 7z signature is found ****************************************************************************/ int IsZipFile (char *buffer) @@ -74,17 +67,28 @@ IsZipFile (char *buffer) if (check[0] == 0x504b0304) // ZIP file return 1; - return 0; + // 7z signature + static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + + int i; + for(i = 0; i < 6; i++) + if(buffer[i] != Signature[i]) + return 0; + + return 2; // 7z archive found } /***************************************************************************** - * UnZipBuffer + * unzip * * It should be noted that there is a limit of 5MB total size for any ROM ******************************************************************************/ +FILE* fatfile; // FAT +u64 discoffset; // DVD +SMBFILE smbfile; // SMB int -UnZipBuffer (unsigned char *outbuffer, int method) +UnZipBuffer (unsigned char *outbuffer, short where) { PKZIPHEADER pkzip; int zipoffset = 0; @@ -97,25 +101,22 @@ UnZipBuffer (unsigned char *outbuffer, int method) int have = 0; char readbuffer[ZIPCHUNK]; char msg[128]; - u64 discoffset = 0; - // Read Zip Header - switch (method) + /*** Read Zip Header ***/ + switch (where) { - case METHOD_SD: - case METHOD_USB: - fseek(fatfile, 0, SEEK_SET); - fread (readbuffer, 1, ZIPCHUNK, fatfile); - break; - - case METHOD_DVD: - discoffset = dvddir; - dvd_read (readbuffer, ZIPCHUNK, discoffset); - break; - - case METHOD_SMB: - SMB_ReadFile(readbuffer, ZIPCHUNK, 0, smbfile); - break; + case 0: // SD Card + fseek(fatfile, 0, SEEK_SET); + fread (readbuffer, 1, ZIPCHUNK, fatfile); + break; + + case 1: // DVD + dvd_read (readbuffer, ZIPCHUNK, discoffset); + break; + + case 2: // From SMB + SMB_ReadFile(readbuffer, ZIPCHUNK, 0, smbfile); + break; } /*** Copy PKZip header to local, used as info ***/ @@ -175,26 +176,25 @@ UnZipBuffer (unsigned char *outbuffer, int method) } while (zs.avail_out == 0); - // Readup the next 2k block + /*** Readup the next 2k block ***/ zipoffset = 0; zipchunk = ZIPCHUNK; - switch (method) + switch (where) { - case METHOD_SD: - case METHOD_USB: - fread (readbuffer, 1, ZIPCHUNK, fatfile); - break; - - case METHOD_DVD: - readoffset += ZIPCHUNK; - dvd_read (readbuffer, ZIPCHUNK, discoffset+readoffset); - break; - - case METHOD_SMB: - readoffset += ZIPCHUNK; - SMB_ReadFile(readbuffer, ZIPCHUNK, readoffset, smbfile); - break; + case 0: // SD Card + fread (readbuffer, 1, ZIPCHUNK, fatfile); + break; + + case 1: // DVD + readoffset += ZIPCHUNK; + dvd_read (readbuffer, ZIPCHUNK, discoffset+readoffset); + break; + + case 2: // From SMB + readoffset += ZIPCHUNK; + SMB_ReadFile(readbuffer, ZIPCHUNK, readoffset, smbfile); + break; } } while (res != Z_STREAM_END); @@ -211,49 +211,75 @@ UnZipBuffer (unsigned char *outbuffer, int method) return 0; } - -/**************************************************************************** - * GetFirstZipFilename - * - * Returns the filename of the first file in the zipped archive - * The idea here is to do the least amount of work required - ***************************************************************************/ - -char * -GetFirstZipFilename (int method) +// Reading from FAT +int +UnZipFATFile (unsigned char *outbuffer, FILE* infile) +{ + fatfile = infile; + return UnZipBuffer(outbuffer, 0); +} +// Reading from DVD +int +UnZipDVDFile (unsigned char *outbuffer, u64 inoffset) +{ + discoffset = inoffset; + return UnZipBuffer(outbuffer, 1); +} +// Reading from SMB +int +UnZipSMBFile (unsigned char *outbuffer, SMBFILE infile) { - char * firstFilename = NULL; - char tempbuffer[ZIPCHUNK]; + smbfile = infile; + return UnZipBuffer(outbuffer, 2); +} - // read start of ZIP - switch (method) - { - case METHOD_SD: // SD Card - case METHOD_USB: // USB - LoadFATFile (tempbuffer, ZIPCHUNK); - break; +/* + * 7-zip functions are below. Have to be written to work with above. + * +else if (selection == 0 && inSz == true) { + rootdir = filelist[1].offset; + rootdirlength = filelist[1].length; + offset = 0; + maxfiles = parsedir(); + inSz = false; + SzClose(); +} +else if (inSz == false && SzDvdIsArchive(filelist[selection].offset) == SZ_OK) { + // parse the 7zip file + ShowAction("Found 7z"); + SzParse(); + if(SzRes == SZ_OK) { + inSz = true; + offset = selection = 0; + } else { + SzDisplayError(SzRes); + } +} +else if (inSz == true) { + // extract the selected ROM from the 7zip file to the buffer + if(SzExtractROM(filelist[selection].offset, nesrom) == true) { + haverom = 1; + inSz = false; + + // go one directory up + rootdir = filelist[1].offset; + rootdirlength = filelist[1].length; + offset = selection = 0; + maxfiles = parsedir(); + } +} +*/ - case METHOD_DVD: // DVD - LoadDVDFile ((unsigned char *)tempbuffer, ZIPCHUNK); - break; - case METHOD_SMB: // From SMB - LoadSMBFile (tempbuffer, ZIPCHUNK); - break; - } - tempbuffer[28] = 0; // truncate - filename length is 2 bytes long (bytes 26-27) - int namelength = tempbuffer[26]; // filename length starts 26 bytes in - firstFilename = &tempbuffer[30]; // first filename of a ZIP starts 31 bytes in - firstFilename[namelength] = 0; // truncate at filename length +/* + * 7-zip functions are below. Have to be written to work with above. - return firstFilename; -} -/**************************************************************************** - * 7z functions - ***************************************************************************/ +#include "7zCrc.h" +#include "7zIn.h" +#include "7zExtract.h" typedef struct _SzFileInStream { @@ -263,6 +289,9 @@ typedef struct _SzFileInStream u64 pos; // current position of the file pointer } SzFileInStream; + + + // 7zip error list char szerrormsg[][30] = { "7z: Data error", @@ -270,8 +299,7 @@ char szerrormsg[][30] = { "7z: CRC Error", "7z: Not implemented", "7z: Fail", - "7z: Archive error", - "7z: Dictionary too large", + "7z: Archive error" }; SZ_RESULT SzRes; @@ -285,66 +313,148 @@ size_t SzBufferSize; size_t SzOffset; size_t SzOutSizeProcessed; CFileItem *SzF; - char sz_buffer[2048]; -int szMethod = 0; - -/**************************************************************************** - * Is7ZipFile - * - * Returns 1 when 7z signature is found - ****************************************************************************/ -int -Is7ZipFile (char *buffer) -{ - unsigned int *check; - check = (unsigned int *) buffer; - // 7z signature - static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; - - int i; - for(i = 0; i < 6; i++) - if(buffer[i] != Signature[i]) - return 0; +// the GC's dvd drive only supports offsets and length which are a multiply of 32 bytes +// additionally the max length of a read is 2048 bytes +// this function removes these limitations +// additionally the 7zip SDK does often read data in 1 byte parts from the DVD even when +// it could read 32 bytes. the dvdsf_buffer has been added to avoid having to read the same sector +// over and over again +unsigned char dvdsf_buffer[DVD_SECTOR_SIZE]; +u64 dvdsf_last_offset = 0; +u64 dvdsf_last_length = 0; + +int dvd_buffered_read(void *dst, u32 len, u64 offset) { + int ret = 0; + + // only read data if the data inside dvdsf_buffer cannot be used + if(offset != dvdsf_last_offset || len > dvdsf_last_length) { + char msg[1024]; + sprintf(msg, "buff_read: len=%d, offset=%llX, UseSD=%d", len, offset, UseSDCARD); + //WaitPrompt(msg); + memset(&dvdsf_buffer, '\0', DVD_SECTOR_SIZE); + if (UseSDCARD) { + if (filehandle == NULL) + GetSDInfo(); + + fseek(filehandle, offset, SEEK_SET); + fread(&dvdsf_buffer, len, 1, filehandle); + } else if (!UseWiiSDCARD) + ret = dvd_read(&dvdsf_buffer, len, offset); + dvdsf_last_offset = offset; + dvdsf_last_length = len; + } - return 1; // 7z archive found + memcpy(dst, &dvdsf_buffer, len); + return ret; } -// display an error message -void SzDisplayError(SZ_RESULT res) -{ - WaitPrompt(szerrormsg[(res - 1)]); +int dvd_safe_read(void *dst_v, u32 len, u64 offset) { + unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector + + // if read size and length are a multiply of DVD_(OFFSET,LENGTH)_MULTIPLY and length < DVD_MAX_READ_LENGTH + // we don't need to fix anything + if(len % DVD_LENGTH_MULTIPLY == 0 && offset % DVD_OFFSET_MULTIPLY == 0 && len <= DVD_MAX_READ_LENGTH) { + char msg[1024]; + sprintf(msg, "simple_safe_read: len=%d, offset=%llX, UseSD=%d", len, offset, UseSDCARD); + //WaitPrompt(msg); + int ret = dvd_buffered_read(buffer, len, offset); + memcpy(dst_v, &buffer, len); + return ret; + } else { + char msg[1024]; + sprintf(msg, "complex_safe_read: len=%d, offset=%llX, UseSD=%d", len, offset, UseSDCARD); + //WaitPrompt(msg); + // no errors yet -> ret = 0 + // the return value of dvd_read will be OR'd with ret + // because dvd_read does return 1 on error and 0 on success and + // because 0 | 1 = 1 ret will also contain 1 if at least one error + // occured and 0 otherwise ;) + int ret = 0; // return value of dvd_read + + // we might need to fix all 3 issues + unsigned char *dst = (unsigned char *)dst_v; // gcc will not allow to use var[num] on void* types + u64 bytesToRead; // the number of bytes we still need to read & copy to the output buffer + u64 currentOffset; // the current dvd offset + u64 bufferOffset; // the current buffer offset + u64 i, j, k; // temporary variables which might be used for different stuff + // unsigned char buffer[DVD_SECTOR_SIZE]; // buffer for one dvd sector + + currentOffset = offset; + bytesToRead = len; + bufferOffset = 0; + + // fix first issue (offset is not a multiply of 32) + if(offset % DVD_OFFSET_MULTIPLY) { + // calcualte offset of the prior 32 byte position + i = currentOffset - (currentOffset % DVD_OFFSET_MULTIPLY); + + // calculate the offset from which the data of the dvd buffer will be copied + j = currentOffset % DVD_OFFSET_MULTIPLY; + + // calculate the number of bytes needed to reach the next DVD_OFFSET_MULTIPLY byte mark + k = DVD_OFFSET_MULTIPLY - j; + + // maybe we'll only need to copy a few bytes and we therefore don't even reach the next sector + if(k > len) { + k = len; + } + + // read 32 bytes from the last 32 byte position + ret |= dvd_buffered_read(buffer, DVD_OFFSET_MULTIPLY, i); + + // copy the bytes to the output buffer and update currentOffset, bufferOffset and bytesToRead + memcpy(&dst[bufferOffset], &buffer[j], k); + currentOffset += k; + bufferOffset += k; + bytesToRead -= k; + } + + // fix second issue (more than 2048 bytes are needed) + if(bytesToRead > DVD_MAX_READ_LENGTH) { + // calculate the number of 2048 bytes sector needed to get all data + i = (bytesToRead - (bytesToRead % DVD_MAX_READ_LENGTH)) / DVD_MAX_READ_LENGTH; + + // read data in 2048 byte sector + for(j = 0; j < i; j++) { + ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read sector + memcpy(&dst[bufferOffset], buffer, DVD_MAX_READ_LENGTH); // copy to output buffer + + // update currentOffset, bufferOffset and bytesToRead + currentOffset += DVD_MAX_READ_LENGTH; + bufferOffset += DVD_MAX_READ_LENGTH; + bytesToRead -= DVD_MAX_READ_LENGTH; + } + } + + // fix third issue (length is not a multiply of 32) + if(bytesToRead) { + ret |= dvd_buffered_read(buffer, DVD_MAX_READ_LENGTH, currentOffset); // read 32 byte from the dvd + memcpy(&dst[bufferOffset], buffer, bytesToRead); // copy bytes to output buffer + } + + //free(tmp); + return ret; + } } -// function used by the 7zip SDK to read data from SD/USB/DVD/SMB -SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) +// function used by the 7zip SDK to read data from the DVD (fread) +SZ_RESULT SzDvdFileReadImp(void *object, void **buffer, size_t maxRequiredSize, size_t *processedSize) { // the void* object is a SzFileInStream SzFileInStream *s = (SzFileInStream *)object; - // calculate offset + // calculate dvd sector offset u64 offset = (u64)(s->offset + s->pos); - if(maxRequiredSize > 2048) - maxRequiredSize = 2048; + if(maxRequiredSize > 2048) + { + maxRequiredSize = 2048; + } // read data - switch(szMethod) - { - case METHOD_SD: - case METHOD_USB: - fseek(fatfile, offset, SEEK_SET); - fread (sz_buffer, 1, maxRequiredSize, fatfile); - break; - case METHOD_DVD: - dvd_safe_read(sz_buffer, maxRequiredSize, offset); - break; - case METHOD_SMB: - SMB_ReadFile(sz_buffer, maxRequiredSize, offset, smbfile); - break; - } - + dvd_safe_read(sz_buffer, maxRequiredSize, offset); *buffer = sz_buffer; *processedSize = maxRequiredSize; s->pos += *processedSize; @@ -352,8 +462,8 @@ SZ_RESULT SzFileReadImp(void *object, void **buffer, size_t maxRequiredSize, siz return SZ_OK; } -// function used by the 7zip SDK to change the filepointer -SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) +// function used by the 7zip SDK to change the filepointer (fseek(object, pos, SEEK_SET)) +SZ_RESULT SzDvdFileSeekImp(void *object, CFileSize pos) { // the void* object is a SzFileInStream SzFileInStream *s = (SzFileInStream *)object; @@ -370,158 +480,126 @@ SZ_RESULT SzFileSeekImp(void *object, CFileSize pos) return SZ_OK; } -/**************************************************************************** - * SzParse - * - * Opens a 7z file, and parses it - * Right now doesn't parse 7z, since we'll always use the first file - * But it could parse the entire 7z for full browsing capability - ***************************************************************************/ - -int SzParse(char * filepath, int method) -{ - int nbfiles = 0; +SZ_RESULT SzDvdIsArchive(u64 dvd_offset) { + // 7z signautre + static Byte Signature[6] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; + Byte Candidate[6]; - // save the offset and the length of this file inside the archive stream structure - SzArchiveStream.offset = filelist[selection].offset; - SzArchiveStream.len = filelist[selection].length; - SzArchiveStream.pos = 0; + // read the data from the DVD + int res = dvd_safe_read (&Candidate, 6, dvd_offset); + char msg[1024]; - // open file - switch (method) - { - case METHOD_SD: - case METHOD_USB: - fatfile = fopen (filepath, "rb"); - if(!fatfile) - return 0; - break; - case METHOD_SMB: - smbfile = OpenSMBFile(filepath); - if(!smbfile) - return 0; - break; - } - - // set szMethod to current chosen load method - szMethod = method; - - // set handler functions for reading data from FAT/SMB/DVD - SzArchiveStream.InStream.Read = SzFileReadImp; - SzArchiveStream.InStream.Seek = SzFileSeekImp; + size_t i; + for(i = 0; i < 6; i++) { + if(Candidate[i] != Signature[i]) { + return SZE_FAIL; + } + } - // set default 7Zip SDK handlers for allocation and freeing memory - SzAllocImp.Alloc = SzAlloc; - SzAllocImp.Free = SzFree; - SzAllocTempImp.Alloc = SzAllocTemp; - SzAllocTempImp.Free = SzFreeTemp; + return SZ_OK; +} - // prepare CRC and 7Zip database structures - InitCrcTable(); - SzArDbExInit(&SzDb); +// display an error message +void SzDisplayError(SZ_RESULT res) +{ + WaitPrompt(szerrormsg[(res - 1)]); +} - // open the archive - SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, - &SzAllocTempImp); +static u64 rootdir; +static int rootdirlength; - if (SzRes != SZ_OK) - { - SzDisplayError(SzRes); - // free memory used by the 7z SDK - SzClose(); - } - else // archive opened successfully - { - if(SzDb.Database.NumFiles > 0) - { - // Parses the 7z into a full file listing +void SzParse(void) { + // save the offset and the length of this file inside the archive stream structure + SzArchiveStream.offset = filelist[selection].offset; + SzArchiveStream.len = filelist[selection].length; + SzArchiveStream.pos = 0; - // erase all previous entries - memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES); + // set handler functions for reading data from DVD and setting the position + SzArchiveStream.InStream.Read = SzDvdFileReadImp; + SzArchiveStream.InStream.Seek = SzDvdFileSeekImp; - // add '..' folder in case the user wants exit the 7z - strncpy(filelist[0].displayname, "..", 2); - filelist[0].flags = 1; - filelist[0].offset = dvddir; - filelist[0].length = dvddirlength; + // set default 7Zip SDK handlers for allocation and freeing memory + SzAllocImp.Alloc = SzAlloc; + SzAllocImp.Free = SzFree; + SzAllocTempImp.Alloc = SzAllocTemp; + SzAllocTempImp.Free = SzFreeTemp; - // get contents and parse them into file list structure - unsigned int SzI, SzJ; - SzJ = 1; - for (SzI = 0; SzI < SzDb.Database.NumFiles; SzI++) - { - SzF = SzDb.Database.Files + SzI; - - // skip directories - if (SzF->IsDirectory) - continue; - - // do not exceed MAXFILES to avoid possible buffer overflows - if (SzJ == (MAXFILES - 1)) - break; - - // parse information about this file to the dvd file list structure - strncpy(filelist[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...) - filelist[SzJ].filename[MAXJOLIET] = 0; // terminate string - strncpy(filelist[SzJ].displayname, SzF->Name, MAXDISPLAY+1); // crop name for display - filelist[SzJ].length = SzF->Size; // filesize - filelist[SzJ].offset = SzI; // the extraction function identifies the file with this number - filelist[SzJ].flags = 0; // only files will be displayed (-> no flags) - SzJ++; - } + // prepare CRC and 7Zip database structures + InitCrcTable(); + SzArDbExInit(&SzDb); - // update maxfiles and select the first entry - offset = selection = 0; - nbfiles = SzJ; - } - else - { - SzArDbExFree(&SzDb, SzAllocImp.Free); - } - } + // open the archive + SzRes = SzArchiveOpen(&SzArchiveStream.InStream, &SzDb, &SzAllocImp, &SzAllocTempImp); - // close file - switch (method) - { - case METHOD_SD: - case METHOD_USB: - fclose(fatfile); - break; - case METHOD_SMB: - SMB_CloseFile (smbfile); - break; - } - return nbfiles; + if(SzRes != SZ_OK) + { + // free memory used by the 7z SDK + SzArDbExFree(&SzDb, SzAllocImp.Free); + return; + } + else + { + // archive opened successfully + + // erase all previous entries + memset(&filelist, 0, sizeof(FILEENTRIES) * MAXFILES); + + // add '../' folder + strncpy(filelist[0].filename, "../", 3); + filelist[0].length = rootdirlength; // store rootdir in case the user wants to go one folder up + filelist[0].offset = rootdir; // -''- rootdir length -''- + filelist[0].flags = 0; + + // get contents and parse them into the dvd file list structure + unsigned int SzI, SzJ; + SzJ = 1; + for(SzI = 0; SzI < SzDb.Database.NumFiles; SzI++) + { + SzF = SzDb.Database.Files + SzI; + + // skip directories + if(SzF->IsDirectory) + { + continue; + } + + // do not exceed MAXFILES to avoid possible buffer overflows + if(SzJ == (MAXFILES - 1)) + { + break; + } + + // parse information about this file to the dvd file list structure + strncpy(filelist[SzJ].filename, SzF->Name, MAXJOLIET); // copy joliet name (useless...) + filelist[SzJ].filename[MAXJOLIET] = 0; // terminate string + filelist[SzJ].length = SzF->Size; // filesize + filelist[SzJ].offset = SzI; // the extraction function identifies the file with this number + filelist[SzJ].flags = 0; // only files will be displayed (-> no flags) + SzJ++; + } + + // update maxfiles and select the first entry + maxfiles = SzJ; + offset = selection = 0; + return; + } } -/**************************************************************************** - * SzClose - * - * Closes a 7z file - ***************************************************************************/ - -void SzClose() +void SzClose(void) { - if(SzDb.Database.NumFiles > 0) - SzArDbExFree(&SzDb, SzAllocImp.Free); + SzArDbExFree(&SzDb, SzAllocImp.Free); } -/**************************************************************************** - * SzExtractFile - * - * Extracts the given file # into the buffer specified - * Must parse the 7z BEFORE running this function - ***************************************************************************/ - -int SzExtractFile(int i, unsigned char *buffer) +bool SzExtractROM(int i, unsigned char *buffer) { + // prepare some variables SzBlockIndex = 0xFFFFFFFF; SzOffset = 0; // Unzip the file - ShowAction("Unzipping file. Please wait..."); - + //ShowAction("Un7zipping file. Please wait..."); + WaitPrompt("Un7zipping file. Please wait..."); SzRes = SzExtract2( &SzArchiveStream.InStream, &SzDb, @@ -534,18 +612,18 @@ int SzExtractFile(int i, unsigned char *buffer) &SzAllocImp, &SzAllocTempImp); - // close 7Zip archive and free memory - SzClose(); - // check for errors if(SzRes != SZ_OK) { - // display error message - SzDisplayError(SzRes); - return 0; + // display error message + WaitPrompt(szerrormsg[(SzRes - 1)]); + return false; } else { - return SzOutSizeProcessed; + // close 7Zip archive and free memory + SzArDbExFree(&SzDb, SzAllocImp.Free); + return true; } } +*/ diff --git a/source/ngc/gcunzip.h b/source/ngc/gcunzip.h index 89b8f5f7..907f59d4 100644 --- a/source/ngc/gcunzip.h +++ b/source/ngc/gcunzip.h @@ -15,11 +15,10 @@ #include extern int IsZipFile (char *buffer); -char * GetFirstZipFilename(int method); -int UnZipBuffer (unsigned char *outbuffer, int method); -int SzParse(char * filepath, int method); -int SzExtractFile(int i, unsigned char *buffer); -void SzClose(); + +int UnZipFATFile (unsigned char *outbuffer, FILE* infile); // Reading from FAT +int UnZipDVDFile (unsigned char *outbuffer, u64 inoffset); // Reading from DVD +int UnZipSMBFile (unsigned char *outbuffer, SMBFILE infile); // Reading from SMB /* * Zip file header definition diff --git a/source/ngc/gcvideo.c b/source/ngc/gcvideo.c index dcc75113..30436f6e 100644 --- a/source/ngc/gcvideo.c +++ b/source/ngc/gcvideo.c @@ -16,14 +16,10 @@ #include #include -#include "driver.h" - #include "gcvideo.h" #include "images/nesback.h" extern unsigned int SMBTimer; -int FDSTimer = 0; -int FDSSwitchRequested; #define TEX_WIDTH 256 #define TEX_HEIGHT 512 @@ -62,29 +58,6 @@ static void copy_to_xfb() { copynow = GX_FALSE; } SMBTimer++; - - // FDS switch disk requested - need to eject, select, and insert - // but not all at once! - if(FDSSwitchRequested) - { - switch(FDSSwitchRequested) - { - case 1: - FCEUI_FDSEject(); // eject disk - FDSSwitchRequested++; - break; - case 2: - if(FDSTimer > 60) - { - FCEUI_FDSSelect(); // select other side - FCEUI_FDSInsert(0); // insert disk - FDSSwitchRequested = 0; - FDSTimer = 0; - } - break; - } - FDSTimer++; - } } /**************************************************************************** diff --git a/source/ngc/gcvideo.h b/source/ngc/gcvideo.h index 1dcc0656..aafd71b1 100644 --- a/source/ngc/gcvideo.h +++ b/source/ngc/gcvideo.h @@ -26,6 +26,5 @@ struct st_palettes { }; extern struct st_palettes palettes[]; -extern int FDSSwitchRequested; #endif diff --git a/source/ngc/menu.c b/source/ngc/menu.c index 4db8a43b..69a0fe16 100644 --- a/source/ngc/menu.c +++ b/source/ngc/menu.c @@ -241,10 +241,6 @@ PreferencesMenu () GCSettings.SaveMethod++; if(GCSettings.SaveMethod == METHOD_MC_SLOTB) GCSettings.SaveMethod++; - prefmenu[6][0] = '\0'; - #else - sprintf (prefmenu[6], "Verify MC Saves %s", - GCSettings.VerifySaves == true ? " ON" : "OFF"); #endif // correct load/save methods out of bounds @@ -283,6 +279,9 @@ PreferencesMenu () else if (GCSettings.AutoSave == 2) sprintf (prefmenu[5],"Auto Save STATE"); else if (GCSettings.AutoSave == 3) sprintf (prefmenu[5],"Auto Save BOTH"); + sprintf (prefmenu[6], "Verify MC Saves %s", + GCSettings.VerifySaves == true ? " ON" : "OFF"); + ret = RunMenu (prefmenu, prefmenuCount, (char*)"Preferences", 16, -1); switch (ret) @@ -355,16 +354,6 @@ GameMenu () while (quit == 0) { - if(nesGameType == 4) // FDS game - { - // disable RAM saving/loading - gamemenu[3][0] = '\0'; - gamemenu[4][0] = '\0'; - - // disable ROM Information - gamemenu[2][0] = '\0'; - } - // disable RAM/STATE saving/loading if AUTO is on if (GCSettings.AutoLoad == 1) // Auto Load RAM gamemenu[3][0] = '\0'; @@ -692,20 +681,20 @@ ConfigureControllers () { case 0: // four score GCSettings.FSDisable ^= 1; - ToggleFourScore(GCSettings.FSDisable, romLoaded); + ToggleFourScore(GCSettings.FSDisable); break; case 1: // zapper GCSettings.zapper -= 1; // we do this so Port 2 is first option shown if(GCSettings.zapper < 0) GCSettings.zapper = 2; - ToggleZapper(GCSettings.zapper, romLoaded); + ToggleZapper(GCSettings.zapper); break; case 2: // zapper crosshair GCSettings.crosshair ^= 1; break; - + case 3: /*** Configure Nunchuk ***/ ConfigureButtons (CTRLR_NUNCHUK); @@ -837,16 +826,12 @@ MainMenu (int selectedMenu) } } - // Wait for buttons to be released - int count = 0; // how long we've been waiting for the user to release the button - while(count < 50 && ( - PAD_ButtonsHeld(0) - #ifdef HW_RVL - || WPAD_ButtonsHeld(0) - #endif - )) - { - VIDEO_WaitVSync(); - count++; - } + /*** Remove any still held buttons ***/ + #ifdef HW_RVL + while( PAD_ButtonsHeld(0) || WPAD_ButtonsHeld(0) ) + VIDEO_WaitVSync(); + #else + while( PAD_ButtonsHeld(0) ) + VIDEO_WaitVSync(); + #endif } diff --git a/source/ngc/menudraw.c b/source/ngc/menudraw.c index ca1fd26b..be471eaf 100644 --- a/source/ngc/menudraw.c +++ b/source/ngc/menudraw.c @@ -439,7 +439,7 @@ DrawMenu (char items[][50], char *title, int maxitems, int selected, int fontsiz else if (i == selected) { for( w = 0; w < line_height; w++ ) - DrawLineFast( 30, 610, n * line_height + (ypos-line_height+6) + w, 0xBB, 0xBB, 0xBB ); + DrawLineFast( 30, 610, n * line_height + (ypos-line_height+6) + w, 0x60, 0x60, 0x60 ); setfontcolour (0xff, 0xff, 0xff); DrawText (x, n * line_height + ypos, items[i]); @@ -605,7 +605,7 @@ ShowFiles (FILEENTRIES filelist[], int maxfiles, int offset, int selection) { /*** Highlighted text entry ***/ for ( w = 0; w < 20; w++ ) - DrawLineFast( 30, 610, ( j * 20 ) + (ypos-16) + w, 0xCC, 0xCC, 0xCC ); + DrawLineFast( 30, 610, ( j * 20 ) + (ypos-16) + w, 0x60, 0x60, 0x60 ); setfontcolour (0xFF, 0xFF, 0xFF); DrawText (50, (j * 20) + ypos, text); diff --git a/source/ngc/pad.c b/source/ngc/pad.c index a7e24344..c2c6bdc7 100644 --- a/source/ngc/pad.c +++ b/source/ngc/pad.c @@ -22,7 +22,6 @@ #include "menu.h" #include "fceustate.h" #include "fceuram.h" -#include "gcvideo.h" #include "filesel.h" extern bool romLoaded; @@ -40,10 +39,10 @@ unsigned int nespadmap[] = { /*** Gamecube controller Padmap ***/ unsigned int gcpadmap[] = { PAD_BUTTON_B, PAD_BUTTON_A, - PAD_TRIGGER_Z, PAD_BUTTON_START, + PAD_TRIGGER_L, PAD_TRIGGER_R, PAD_BUTTON_UP, PAD_BUTTON_DOWN, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT, - PAD_TRIGGER_L + PAD_TRIGGER_Z // insert coin for VS games }; /*** Wiimote Padmap ***/ unsigned int wmpadmap[] = { @@ -51,7 +50,7 @@ unsigned int wmpadmap[] = { WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS, WPAD_BUTTON_RIGHT, WPAD_BUTTON_LEFT, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, - WPAD_BUTTON_A + WPAD_BUTTON_A // insert coin for VS games }; /*** Classic Controller Padmap ***/ unsigned int ccpadmap[] = { @@ -59,7 +58,7 @@ unsigned int ccpadmap[] = { WPAD_CLASSIC_BUTTON_MINUS, WPAD_CLASSIC_BUTTON_PLUS, WPAD_CLASSIC_BUTTON_UP, WPAD_CLASSIC_BUTTON_DOWN, WPAD_CLASSIC_BUTTON_LEFT, WPAD_CLASSIC_BUTTON_RIGHT, - WPAD_CLASSIC_BUTTON_A + WPAD_CLASSIC_BUTTON_A // insert coin for VS games }; /*** Nunchuk + wiimote Padmap ***/ unsigned int ncpadmap[] = { @@ -67,7 +66,7 @@ unsigned int ncpadmap[] = { WPAD_BUTTON_MINUS, WPAD_BUTTON_PLUS, WPAD_BUTTON_UP, WPAD_BUTTON_DOWN, WPAD_BUTTON_LEFT, WPAD_BUTTON_RIGHT, - WPAD_BUTTON_A + WPAD_BUTTON_A // insert coin for VS games }; static uint32 JSReturn = 0; @@ -87,19 +86,19 @@ void InitialisePads() FCEUI_SetInput(0, SI_GAMEPAD, InputDPR, 0); FCEUI_SetInput(1, SI_GAMEPAD, InputDPR, 0); - ToggleFourScore(GCSettings.FSDisable, true); - ToggleZapper(GCSettings.zapper, true); + ToggleFourScore(GCSettings.FSDisable); + ToggleZapper(GCSettings.zapper); } -void ToggleFourScore(int set, bool loaded) +void ToggleFourScore(int set) { - if(loaded) + if(romLoaded) FCEUI_DisableFourScore(set); } -void ToggleZapper(int set, bool loaded) +void ToggleZapper(int set) { - if(loaded) + if(romLoaded) { // set defaults zapperdata[0]=NULL; @@ -368,8 +367,9 @@ unsigned char DecodeJoy( unsigned short pad ) } #endif - // Report pressed buttons (gamepads) + /*** Report pressed buttons (gamepads) ***/ int i; + for (i = 0; i < MAXJP; i++) { if ( (jp & gcpadmap[i]) // gamecube controller @@ -380,29 +380,24 @@ unsigned char DecodeJoy( unsigned short pad ) #endif ) { - // if zapper is on, ignore all buttons except START and SELECT - if(!GCSettings.zapper || nespadmap[i] == JOY_START || nespadmap[i] == JOY_SELECT) + if(nespadmap[i] > 0) + J |= nespadmap[i]; + else { - if(nespadmap[i] > 0) + if(nesGameType == 4) // FDS { - J |= nespadmap[i]; + /* these commands shouldn't be issued in parallel but this + * allows us to only map one button for both! + * the gamer must just have to press the button twice */ + FCEUI_FDSInsert(0); // eject / insert disk + FCEUI_FDSSelect(); // select other side } else - { - if(nesGameType == 4) // FDS - { - /* the commands shouldn't be issued in parallel so - * we'll delay them so the virtual FDS has a chance - * to process them - */ - FDSSwitchRequested = 1; - } - else - FCEUI_VSUniCoin(); // insert coin for VS Games - } + FCEU_DoSimpleCommand(0x07); // insert coin for VS Games } } } + // zapper enabled if(GCSettings.zapper) { @@ -423,16 +418,6 @@ unsigned char DecodeJoy( unsigned short pad ) myzappers[z][2] |= 2; } - // VS zapper games - if ( (jp & PAD_BUTTON_B) // gamecube controller - #ifdef HW_RVL - || (wp & WPAD_BUTTON_1) // wiimote - #endif - ) - { - FCEUI_VSUniCoin(); // insert coin for VS zapper games - } - // cursor position UpdateCursorPosition(0); // update cursor for wiimote 1 myzappers[z][0] = pos_x; @@ -460,7 +445,7 @@ void GetJoy() #endif // request to go back to menu - if ((gc_px < -70) || ((jp & PAD_BUTTON_START) && (jp & PAD_BUTTON_A)) + if ((gc_px < -70) || (jp & PAD_BUTTON_START) #ifdef HW_RVL || (wm_pb & WPAD_BUTTON_HOME) || (wm_pb & WPAD_CLASSIC_BUTTON_HOME) diff --git a/source/ngc/pad.h b/source/ngc/pad.h index 4573b4f1..c320a121 100644 --- a/source/ngc/pad.h +++ b/source/ngc/pad.h @@ -27,8 +27,8 @@ s8 WPAD_StickX(u8 chan,u8 right); s8 WPAD_StickY(u8 chan, u8 right); void InitialisePads(); void GetJoy(); -void ToggleFourScore(int set, bool loaded); -void ToggleZapper(int set, bool loaded); +void ToggleFourScore(int set); +void ToggleZapper(int set); void DrawCursor(); #endif diff --git a/source/ngc/preferences.c b/source/ngc/preferences.c index 43d70287..72b231ae 100644 --- a/source/ngc/preferences.c +++ b/source/ngc/preferences.c @@ -256,7 +256,7 @@ decodePrefsData (int method) if(verMajor == '2' && verPoint < '3') // less than version 2.0.3 return false; // reset settings - else if(verMajor > '2' || verMinor > '0' || verPoint > '4') // some future version + else if(verMajor > '2' || verMinor > '0' || verPoint > '3') // some future version return false; // reset settings // File Settings @@ -304,9 +304,7 @@ decodePrefsData (int method) bool SavePrefs (int method, bool silent) { - // there's no point in saving SMB settings TO SMB, because then we'll have no way to load them the next time! - // so instead we'll save using whatever other method is available (eg: SD) - if(method == METHOD_AUTO || method == METHOD_SMB) + if(method == METHOD_AUTO) method = autoSaveMethod(); char filepath[1024]; diff --git a/source/ngc/smbop.c b/source/ngc/smbop.c index 68dd79fb..1bb5afd6 100644 --- a/source/ngc/smbop.c +++ b/source/ngc/smbop.c @@ -31,10 +31,7 @@ bool networkShareInit = false; unsigned int SMBTimer = 0; #define SMBTIMEOUT ( 3600 ) // Some implementations timeout in 10 minutes -// SMB connection/file handles - the only ones we should ever use! SMBCONN smbconn; -SMBFILE smbfile; - #define ZIPCHUNK 16384 /**************************************************************************** @@ -204,7 +201,6 @@ ParseSMBdirectory () filelist[filecount].displayname[MAXDISPLAY] = 0; strcpy (filelist[filecount].filename, smbdir.name); - filelist[filecount].offset = 0; filecount++; } } while (SMB_FindNext (&smbdir, smbconn) == SMB_SUCCESS); @@ -218,58 +214,24 @@ ParseSMBdirectory () return filecount; } -/**************************************************************************** - * Open SMB file - ***************************************************************************/ - -SMBFILE OpenSMBFile(char * filepath) -{ - return SMB_OpenFile (SMBPath(filepath), SMB_OPEN_READING, SMB_OF_OPEN, smbconn); -} - /**************************************************************************** * Load SMB file - * rom - pointer to memory where ROM will be stored - * length - # bytes to read (0 for all) - ***************************************************************************/ + ****************************************************************************/ int -LoadSMBFile (char * rom, int length) +LoadSMBFile () { char filepath[MAXPATHLEN]; /* Check filename length */ - if (!MakeROMPath(filepath, METHOD_SMB)) + if ((strlen(currentdir)+1+strlen(filelist[selection].filename)) < MAXPATHLEN) + sprintf(filepath, "%s/%s",currentdir,filelist[selection].filename); + else { WaitPrompt((char*) "Maximum filepath length reached!"); return -1; } - return LoadBufferFromSMB(rom, filepath, length, NOTSILENT); -} - -/**************************************************************************** - * LoadSMBSzFile - * Loads the selected file # from the specified 7z into rbuffer - * Returns file size - ***************************************************************************/ -int -LoadSMBSzFile(char * filepath, unsigned char * rbuffer) -{ - if(!ConnectShare (NOTSILENT)) - return 0; - smbfile = OpenSMBFile(filepath); - - if (smbfile) - { - u32 size = SzExtractFile(filelist[selection].offset, rbuffer); - SMB_CloseFile (smbfile); - return size; - } - else - { - WaitPrompt((char*) "Error opening file"); - return 0; - } + return LoadBufferFromSMB((char *)nesrom, SMBPath(filepath), NOTSILENT); } /**************************************************************************** @@ -281,6 +243,7 @@ SaveBufferToSMB (char *filepath, int datasize, bool silent) if(!ConnectShare (NOTSILENT)) return 0; + SMBFILE smbfile; int dsize = datasize; int wrote = 0; int boffset = 0; @@ -318,25 +281,28 @@ SaveBufferToSMB (char *filepath, int datasize, bool silent) /**************************************************************************** * Load up a buffer from SMB file - ***************************************************************************/ + ****************************************************************************/ // no buffer is specified - so use savebuffer int LoadSaveBufferFromSMB (char *filepath, bool silent) { - return LoadBufferFromSMB((char *)savebuffer, filepath, 0, silent); + return LoadBufferFromSMB((char *)savebuffer, filepath, silent); } int -LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent) +LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent) { if(!ConnectShare (NOTSILENT)) return 0; - smbfile = OpenSMBFile(filepath); + SMBFILE smbfile; int ret; int boffset = 0; + smbfile = + SMB_OpenFile (SMBPath(filepath), SMB_OPEN_READING, SMB_OF_OPEN, smbconn); + if (!smbfile) { if(!silent) @@ -348,24 +314,25 @@ LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent) return 0; } - if(length > 0) // do a partial read (eg: to check file header) + ret = SMB_ReadFile (sbuffer, 1024, boffset, smbfile); + + int r = IsZipFile (sbuffer); + + if(r == 2) // 7z + { + WaitPrompt ((char *)"7z files are not supported!"); + return 0; + } + + if (r) { - boffset = SMB_ReadFile (sbuffer, length, 0, smbfile); + boffset = UnZipSMBFile ((unsigned char *)sbuffer, smbfile); // unzip from SMB } - else // load whole file + else { - ret = SMB_ReadFile (sbuffer, 1024, boffset, smbfile); - - if (IsZipFile (sbuffer)) - { - boffset = UnZipBuffer ((unsigned char *)sbuffer, METHOD_SMB); // unzip from SMB - } - else - { - // Just load the file up - while ((ret = SMB_ReadFile (sbuffer + boffset, 1024, boffset, smbfile)) > 0) - boffset += ret; - } + // Just load the file up + while ((ret = SMB_ReadFile (sbuffer + boffset, 1024, boffset, smbfile)) > 0) + boffset += ret; } SMB_CloseFile (smbfile); diff --git a/source/ngc/smbop.h b/source/ngc/smbop.h index e356707b..ff4dec90 100644 --- a/source/ngc/smbop.h +++ b/source/ngc/smbop.h @@ -10,22 +10,17 @@ ****************************************************************************/ #ifndef _SMBOP_H_ -#define _SMBOP_H_ -#include +#define _SMBOP_H_ bool InitializeNetwork(bool silent); bool ConnectShare (bool silent); char * SMBPath(char * path); int UpdateSMBdirname(); int ParseSMBdirectory (); -SMBFILE OpenSMBFile(char * filepath); -int LoadSMBFile (char * fbuffer, int length); -int LoadSMBSzFile(char * filepath, unsigned char * rbuffer); +int LoadSMBFile (); int LoadSaveBufferFromSMB (char *filepath, bool silent); -int LoadBufferFromSMB (char * sbuffer, char *filepath, int length, bool silent); +int LoadBufferFromSMB (char * sbuffer, char *filepath, bool silent); int SaveBufferToSMB (char *filepath, int datasize, bool silent); -extern SMBFILE smbfile; - #endif diff --git a/source/sz/7zDecode.c b/source/sz/7zDecode.c index 12198eea..7b583196 100644 --- a/source/sz/7zDecode.c +++ b/source/sz/7zDecode.c @@ -47,7 +47,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #else const Byte *inBuffer, #endif - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain) { UInt32 si; @@ -109,7 +109,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, lzmaCallback.InCallback.Read = LzmaReadImp; #endif - if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; @@ -126,7 +126,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, if (state.Dictionary == 0) { allocMain->Free(state.Probs); - return SZE_OUTOFMEMORYDIC; + return SZE_OUTOFMEMORY; } } LzmaDecoderInit(&state); @@ -157,7 +157,7 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, // like SzDecode but uses less memory SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, ISzInStream *inStream, - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain, size_t *fileOffset, size_t *fileSize) { @@ -220,7 +220,7 @@ SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, lzmaCallback.InCallback.Read = LzmaReadImp; #endif - if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, + if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items, coder->Properties.Capacity) != LZMA_RESULT_OK) return SZE_FAIL; @@ -240,122 +240,116 @@ SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, } } LzmaDecoderInit(&state); - + // allocate memory for the temporary buffer Byte *tmpBuffer = (Byte *)allocMain->Alloc(_LZMA_TEMP_BUFFER_SIZE); - + // variables containing the number of the first and the last bytes of the buffer - size_t bufferStart, bufferEnd; - bufferStart = bufferEnd = 0; - - // integers contains the offset, the size and the already copied data which will be - // copied from the tmpBuffer to outBuffer - size_t copyOffset, copySize, copyDone; - copyOffset = copySize = copyDone = 0; - - UInt32 i = 0; - int bytesToCopy = 0; - - // decompress data in _LZMA_TEMP_BUFFER_SIZE byte steps and copy the wanted file to outBuffer - do - { - if((*fileSize - copyDone) >= _LZMA_TEMP_BUFFER_SIZE) - bytesToCopy = _LZMA_TEMP_BUFFER_SIZE; - else - bytesToCopy = (*fileSize - copyDone); - - // decompress next bytes - result = LzmaDecode(&state, - #ifdef _LZMA_IN_CB - &lzmaCallback.InCallback, - #else - //inBuffer, (SizeT)inSize, &inProcessed, //TODO! - #endif - tmpBuffer, bytesToCopy, &outSizeProcessedLoc - ); - - // check result - if(result == LZMA_RESULT_DATA_ERROR) - { - return SZE_DATA_ERROR; - } - if(result != LZMA_RESULT_OK) - { - return SZE_FAIL; - } - - // normally this should never happen - if(outSizeProcessedLoc > _LZMA_TEMP_BUFFER_SIZE) - { - return SZE_FAIL; - } - - // update bufferStart and bufferEnd - bufferStart = _LZMA_TEMP_BUFFER_SIZE * i; - bufferEnd = bufferStart + outSizeProcessedLoc; - i++; - - // calculate copy offset and size - if(*fileOffset > bufferEnd) - { - // we haven't reached the start of the file yet - continue; - } - - // calculate offset - if(*fileOffset < bufferStart) - { - // the file has already started before this decompression step - copyOffset = 0; - } - else - { - // the file starts somewhere inside this buffer - copyDone = 0; - copyOffset = _LZMA_TEMP_BUFFER_SIZE - (bufferEnd - *fileOffset); - } - - // calculate size - if((*fileOffset + *fileSize) > bufferEnd) - { - // we'll need the whole buffer after copyOffset - copySize = _LZMA_TEMP_BUFFER_SIZE - copyOffset; - } - else - { - // we'll stop somewhere inside the buffer - copySize = (*fileOffset + *fileSize) - (bufferStart + copyOffset); - } - - // copy bytes to the real output buffer - if(copySize == 0) - { - continue; - } - // printf("memcpy(outBuffer + %d, tmpBuffer + %d, %d)\n", copyDone, copyOffset, copySize); - memcpy(outBuffer + copyDone, tmpBuffer + copyOffset, copySize); - copyDone += copySize; - } - while((*fileOffset + *fileSize) > bufferEnd); - - /* result = LzmaDecode(&state, - #ifdef _LZMA_IN_CB - &lzmaCallback.InCallback, - #else - inBuffer, (SizeT)inSize, &inProcessed, - #endif - outBuffer, (SizeT)outSize, &outSizeProcessedLoc);*/ - //*outSizeProcessed = (size_t)outSizeProcessedLoc; - *outSizeProcessed = copyDone; - allocMain->Free(tmpBuffer); // free the temporary buffer again - allocMain->Free(state.Probs); - allocMain->Free(state.Dictionary); - /* if (result == LZMA_RESULT_DATA_ERROR) - return SZE_DATA_ERROR; - if (result != LZMA_RESULT_OK) - return SZE_FAIL;*/ - return SZ_OK; - } - return SZE_NOTIMPL; - } - #endif + size_t bufferStart, bufferEnd; + bufferStart = bufferEnd = 0; + + // integers contains the offset, the size and the already copied data which will be + // copied from the tmpBuffer to outBuffer + size_t copyOffset, copySize, copyDone; + copyOffset = copySize = copyDone = 0; + + UInt32 i = 0; + + // decompress data in _LZMA_TEMP_BUFFER_SIZE byte steps and copy the wanted file to outBuffer + do + { + // decompress next bytes + result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + //inBuffer, (SizeT)inSize, &inProcessed, //TODO! + #endif + tmpBuffer, _LZMA_TEMP_BUFFER_SIZE, &outSizeProcessedLoc + ); + + // check result + if(result == LZMA_RESULT_DATA_ERROR) + { + return SZE_DATA_ERROR; + } + if(result != LZMA_RESULT_OK) + { + return SZE_FAIL; + } + + // normally this should never happen + if(outSizeProcessedLoc > _LZMA_TEMP_BUFFER_SIZE) + { + return SZE_FAIL; + } + + // update bufferStart and bufferEnd + bufferStart = _LZMA_TEMP_BUFFER_SIZE * i; + bufferEnd = bufferStart + outSizeProcessedLoc; + i++; + + // calculate copy offset and size + if(*fileOffset > bufferEnd) + { + // we haven't reached the start of the file yet + continue; + } + + // calculate offset + if(*fileOffset < bufferStart) + { + // the file has already started before this decompression step + copyOffset = 0; + } + else + { + // the file starts somewhere inside this buffer + copyDone = 0; + copyOffset = _LZMA_TEMP_BUFFER_SIZE - (bufferEnd - *fileOffset); + } + + // calculate size + if((*fileOffset + *fileSize) > bufferEnd) + { + // we'll need the whole buffer after copyOffset + copySize = _LZMA_TEMP_BUFFER_SIZE - copyOffset; + } + else + { + // we'll stop somewhere inside the buffer + copySize = (*fileOffset + *fileSize) - (bufferStart + copyOffset); + } + + // copy bytes to the real output buffer + if(copySize == 0) + { + continue; + } + // printf("memcpy(outBuffer + %d, tmpBuffer + %d, %d)\n", copyDone, copyOffset, copySize); + memcpy(outBuffer + copyDone, tmpBuffer + copyOffset, copySize); + copyDone += copySize; + } + while((*fileOffset + *fileSize) > bufferEnd); + +/* result = LzmaDecode(&state, + #ifdef _LZMA_IN_CB + &lzmaCallback.InCallback, + #else + inBuffer, (SizeT)inSize, &inProcessed, + #endif + outBuffer, (SizeT)outSize, &outSizeProcessedLoc);*/ + //*outSizeProcessed = (size_t)outSizeProcessedLoc; + *outSizeProcessed = copyDone; + allocMain->Free(tmpBuffer); // free the temporary buffer again + allocMain->Free(state.Probs); + allocMain->Free(state.Dictionary); +/* if (result == LZMA_RESULT_DATA_ERROR) + return SZE_DATA_ERROR; + if (result != LZMA_RESULT_OK) + return SZE_FAIL;*/ + return SZ_OK; + } + return SZE_NOTIMPL; +} +#endif diff --git a/source/sz/7zDecode.h b/source/sz/7zDecode.h index 9f15ba16..9506e59d 100644 --- a/source/sz/7zDecode.h +++ b/source/sz/7zDecode.h @@ -19,17 +19,17 @@ SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder, #else const Byte *inBuffer, #endif - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain); #ifdef _LZMA_OUT_READ #ifndef _LZMA_TEMP_BUFFER_SIZE -#define _LZMA_TEMP_BUFFER_SIZE (2048) // size of the temporary buffer in bytes +#define _LZMA_TEMP_BUFFER_SIZE (1 << 15) // size of the temporary buffer in bytes #endif SZ_RESULT SzDecode2(const CFileSize *packSizes, const CFolder *folder, ISzInStream *stream, - Byte *outBuffer, size_t outSize, + Byte *outBuffer, size_t outSize, size_t *outSizeProcessed, ISzAlloc *allocMain, size_t *fileOffset, size_t *fileSize); #endif // #ifdef _LZMA_OUT_READ diff --git a/source/sz/7zExtract.c b/source/sz/7zExtract.c index 13ba62ce..9a82ea42 100644 --- a/source/sz/7zExtract.c +++ b/source/sz/7zExtract.c @@ -5,14 +5,14 @@ #include "7zCrc.h" SZ_RESULT SzExtract( - ISzInStream *inStream, + ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, - Byte **outBuffer, + Byte **outBuffer, size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, + size_t *offset, + size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { @@ -41,9 +41,9 @@ SZ_RESULT SzExtract( *blockIndex = folderIndex; allocMain->Free(*outBuffer); *outBuffer = 0; - + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); - + #ifndef _LZMA_IN_CB if (packSize != 0) { @@ -67,12 +67,12 @@ SZ_RESULT SzExtract( if (res == SZ_OK) { size_t outRealSize; - res = SzDecode(db->Database.PackSizes + - db->FolderStartPackStreamIndex[folderIndex], folder, + res = SzDecode(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else - inBuffer, + inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp); if (res == SZ_OK) @@ -96,7 +96,7 @@ SZ_RESULT SzExtract( } if (res == SZ_OK) { - UInt32 i; + UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) @@ -118,14 +118,14 @@ SZ_RESULT SzExtract( #ifdef _LZMA_OUT_READ // similar to SzExtract but needs less memory SZ_RESULT SzExtract2( - ISzInStream *inStream, + ISzInStream *inStream, CArchiveDatabaseEx *db, UInt32 fileIndex, UInt32 *blockIndex, - Byte **outBuffer, + Byte **outBuffer, size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, + size_t *offset, + size_t *outSizeProcessed, ISzAlloc *allocMain, ISzAlloc *allocTemp) { @@ -158,9 +158,9 @@ SZ_RESULT SzExtract2( allocMain->Free(*outBuffer); *outBuffer = 0; #endif - + RINOK(inStream->Seek(inStream, SzArDbGetFolderStreamPos(db, folderIndex, 0))); - + #ifndef _LZMA_IN_CB if (packSize != 0) { @@ -176,7 +176,7 @@ SZ_RESULT SzExtract2( { // calculate file offset and filesize CFileItem *fileItem = db->Database.Files + fileIndex; - UInt32 i; + UInt32 i; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; @@ -192,14 +192,14 @@ SZ_RESULT SzExtract2( } if (res == SZ_OK) { - + size_t outRealSize; - res = SzDecode2(db->Database.PackSizes + - db->FolderStartPackStreamIndex[folderIndex], folder, + res = SzDecode2(db->Database.PackSizes + + db->FolderStartPackStreamIndex[folderIndex], folder, #ifdef _LZMA_IN_CB inStream, #else - inBuffer, + inBuffer, #endif *outBuffer, (size_t)unPackSize, &outRealSize, allocTemp, offset, outSizeProcessed @@ -226,24 +226,24 @@ SZ_RESULT SzExtract2( } if (res == SZ_OK) { -/* UInt32 i; +/* UInt32 i; CFileItem *fileItem = db->Database.Files + fileIndex; *offset = 0; for(i = db->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) *offset += (UInt32)db->Database.Files[i].Size; *outSizeProcessed = (size_t)fileItem->Size;*/ - //CFileItem *fileItem = db->Database.Files + fileIndex; + CFileItem *fileItem = db->Database.Files + fileIndex; if (/**offset +*/ *outSizeProcessed > *outBufferSize) return SZE_FAIL; { - //if (fileItem->IsFileCRCDefined) - //{ - // if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed)) - // res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR? - //} + if (fileItem->IsFileCRCDefined) + { + if (!CrcVerifyDigest(fileItem->FileCRC, *outBuffer/* + *offset*/, *outSizeProcessed)) + res = SZE_CRC_ERROR; // why does SzExtract return SZE_FAIL when we can return SZE_CRC_ERROR? + } } } - + // change *offset to 0 because SzExtract normally decompresses the whole solid block // and sets *offset to the offset of the wanted file. // SzDecode2 does only copy the needed file to the output buffer and has to set *offset diff --git a/source/sz/7zTypes.h b/source/sz/7zTypes.h index fa4c5c3c..817d9215 100644 --- a/source/sz/7zTypes.h +++ b/source/sz/7zTypes.h @@ -5,15 +5,13 @@ #ifndef _7ZIP_BYTE_DEFINED #define _7ZIP_BYTE_DEFINED -#ifndef ZCONF_H typedef unsigned char Byte; -#endif -#endif +#endif #ifndef _7ZIP_UINT16_DEFINED #define _7ZIP_UINT16_DEFINED typedef unsigned short UInt16; -#endif +#endif #ifndef _7ZIP_UINT32_DEFINED #define _7ZIP_UINT32_DEFINED @@ -22,7 +20,7 @@ typedef unsigned long UInt32; #else typedef unsigned int UInt32; #endif -#endif +#endif /* #define _SZ_NO_INT_64 */ /* define it your compiler doesn't support long long int */ @@ -46,9 +44,9 @@ typedef unsigned long long int UInt64; #ifndef CFileSize #ifdef _SZ_FILE_SIZE_64 -typedef UInt64 CFileSize; +typedef UInt64 CFileSize; #else -typedef UInt32 CFileSize; +typedef UInt32 CFileSize; #endif #endif @@ -64,8 +62,6 @@ typedef UInt32 CFileSize; #define SZE_ARCHIVE_ERROR (6) -#define SZE_OUTOFMEMORYDIC (7) - #define RINOK(x) { int __result_ = (x); if(__result_ != 0) return __result_; } #endif