From 83bd0b76aba19ff62368cfee76089e15579e3b7c Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 10 Mar 2007 23:50:03 +0000 Subject: [PATCH] support for zipped ISOs git-svn-id: file:///home/notaz/opt/svn/PicoDrive@65 be3aeb3a-fb24-0410-a615-afba39da0efa --- Pico/Area.c | 20 ++-- Pico/Cart.c | 218 +++++++++++++++++++++++++++------------- Pico/Pico.h | 20 +++- Pico/PicoInt.h | 2 +- Pico/cd/Area.c | 3 +- Pico/cd/cd_file.c | 40 +++----- Pico/cd/cd_sys.h | 7 +- platform/gp2x/Makefile | 2 +- platform/gp2x/emu.c | 48 ++++----- platform/gp2x/menu.c | 2 +- platform/linux/Makefile | 2 +- platform/linux/gp2x.c | 1 + unzip/unzip.c | 10 +- unzip/unzip.h | 2 + unzip/unzip_stream.c | 182 +++++++++++++++++++++++++++++++++ unzip/unzip_stream.h | 4 + zlib/gzio.c | 6 +- 17 files changed, 413 insertions(+), 156 deletions(-) create mode 100644 unzip/unzip_stream.c create mode 100644 unzip/unzip_stream.h diff --git a/Pico/Area.c b/Pico/Area.c index e4f680b..158c111 100644 --- a/Pico/Area.c +++ b/Pico/Area.c @@ -63,11 +63,13 @@ int PicoAreaPackCpu(unsigned char *cpu, int is_sub) #endif #ifdef EMU_M68K - m68ki_cpu_core *context = is_sub ? &PicoS68kCPU : &PicoM68kCPU; - memcpy(cpu,context->dar,0x40); - pc=context->pc; + void *oldcontext = m68ki_cpu_p; + m68k_set_context(is_sub ? &PicoS68kCPU : &PicoM68kCPU); + memcpy(cpu,m68ki_cpu_p->dar,0x40); + pc=m68ki_cpu_p->pc; *(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR); - *(unsigned int *)(cpu+0x48)=context->sp[0]; + *(unsigned int *)(cpu+0x48)=m68ki_cpu_p->sp[0]; + m68k_set_context(oldcontext); #endif *(unsigned int *)(cpu+0x40)=pc; @@ -94,11 +96,13 @@ int PicoAreaUnpackCpu(unsigned char *cpu, int is_sub) #endif #ifdef EMU_M68K - m68ki_cpu_core *context = is_sub ? &PicoS68kCPU : &PicoM68kCPU; - memcpy(context->dar,cpu,0x40); - context->pc=*(unsigned int *)(cpu+0x40); + void *oldcontext = m68ki_cpu_p; + m68k_set_context(is_sub ? &PicoS68kCPU : &PicoM68kCPU); + memcpy(m68ki_cpu_p->dar,cpu,0x40); + m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40); m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44)); - context->sp[0]=*(unsigned int *)(cpu+0x48); + m68ki_cpu_p->sp[0]=*(unsigned int *)(cpu+0x48); + m68k_set_context(oldcontext); #endif return 0; } diff --git a/Pico/Cart.c b/Pico/Cart.c index d3e7743..0762473 100644 --- a/Pico/Cart.c +++ b/Pico/Cart.c @@ -8,6 +8,152 @@ #include "PicoInt.h" +#include "../zlib/zlib.h" +#include "../unzip/unzip.h" +#include "../unzip/unzip_stream.h" + +static char *rom_exts[] = { "bin", "gen", "smd", "iso" }; + + +pm_file *pm_open(const char *path) +{ + pm_file *file = NULL; + const char *ext; + FILE *f; + + if (path == NULL) return NULL; + + if (strlen(path) < 5) ext = NULL; // no ext + else ext = path + strlen(path) - 3; + + if (ext && strcasecmp(ext, "zip") == 0) + { + struct zipent *zipentry; + gzFile gzf = NULL; + ZIP *zipfile; + int i; + + zipfile = openzip(path); + + if (zipfile != NULL) + { + /* search for suitable file (right extension or large enough file) */ + while ((zipentry = readzip(zipfile)) != NULL) + { + if (zipentry->uncompressed_size >= 128*1024) goto found_rom_zip; + if (strlen(zipentry->name) < 5) continue; + + ext = zipentry->name+strlen(zipentry->name)-3; + for (i = 0; i < sizeof(rom_exts)/sizeof(rom_exts[0]); i++) + if (!strcasecmp(ext, rom_exts[i]) == 0) goto found_rom_zip; + } + + /* zipfile given, but nothing found suitable for us inside */ + goto zip_failed; + +found_rom_zip: + /* try to convert to gzip stream, so we could use standard gzio functions from zlib */ + gzf = zip2gz(zipfile, zipentry); + if (gzf == NULL) goto zip_failed; + + file = malloc(sizeof(*file)); + if (file == NULL) goto zip_failed; + file->file = zipfile; + file->param = gzf; + file->size = zipentry->uncompressed_size; + file->type = PMT_ZIP; + return file; + +zip_failed: + if (gzf) { + gzclose(gzf); + zipfile->fp = NULL; // gzclose() closed it + } + closezip(zipfile); + return NULL; + } + } + + /* not a zip, treat as uncompressed file */ + f = fopen(path, "rb"); + if (f == NULL) return NULL; + + file = malloc(sizeof(*file)); + if (file == NULL) { + fclose(f); + return NULL; + } + fseek(f, 0, SEEK_END); + file->file = f; + file->param = NULL; + file->size = ftell(f); + file->type = PMT_UNCOMPRESSED; + fseek(f, 0, SEEK_SET); + return file; +} + +size_t pm_read(void *ptr, size_t bytes, pm_file *stream) +{ + int ret; + + if (stream->type == PMT_UNCOMPRESSED) + { + ret = fread(ptr, 1, bytes, stream->file); + } + else if (stream->type == PMT_ZIP) + { + gzFile gf = stream->param; + int err; + ret = gzread(gf, ptr, bytes); + err = gzerror2(gf); + if (ret > 0 && (err == Z_DATA_ERROR || err == Z_STREAM_END)) + /* we must reset stream pointer or else next seek/read fails */ + gzrewind(gf); + } + else + ret = 0; + + return ret; +} + +int pm_seek(pm_file *stream, long offset, int whence) +{ + if (stream->type == PMT_UNCOMPRESSED) + { + return fseek(stream->file, offset, whence); + } + else if (stream->type == PMT_ZIP) + { + return gzseek((gzFile) stream->param, offset, whence); + } + else + return -1; +} + +int pm_close(pm_file *fp) +{ + int ret = 0; + + if (fp == NULL) return EOF; + + if (fp->type == PMT_UNCOMPRESSED) + { + fclose(fp->file); + } + else if (fp->type == PMT_ZIP) + { + ZIP *zipfile = fp->file; + gzclose((gzFile) fp->param); + zipfile->fp = NULL; // gzclose() closed it + closezip(zipfile); + } + else + ret = EOF; + + free(fp); + return ret; +} + void Byteswap(unsigned char *data,int len) { @@ -86,12 +232,12 @@ static unsigned char *PicoCartAlloc(int filesize) return rom; } -int PicoCartLoad(FILE *f,unsigned char **prom,unsigned int *psize) +int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize) { unsigned char *rom=NULL; int size; if (f==NULL) return 1; - fseek(f,0,SEEK_END); size=ftell(f); fseek(f,0,SEEK_SET); + size=f->size; if (size <= 0) return 1; size=(size+3)&~3; // Round up to a multiple of 4 @@ -99,7 +245,7 @@ int PicoCartLoad(FILE *f,unsigned char **prom,unsigned int *psize) rom=PicoCartAlloc(size); if (rom==NULL) return 1; // { fclose(f); return 1; } - fread(rom,1,size,f); // Load up the rom + pm_read(rom,size,f); // Load up the rom // maybe we are loading MegaCD BIOS? if (!(PicoMCD&1) && size == 0x20000 && (!strncmp((char *)rom+0x124, "BOOT", 4) || !strncmp((char *)rom+0x128, "BOOT", 4))) { @@ -139,69 +285,3 @@ int PicoUnloadCart(unsigned char* romdata) return 0; } - -#ifdef _UNZIP_SUPPORT - -// notaz -#include "../unzip/unzip.h" - -// nearly same as PicoCartLoad, but works with zipfiles -int CartLoadZip(const char *fname, unsigned char **prom, unsigned int *psize) -{ - unsigned char *rom=0; - struct zipent* zipentry; - int size; - ZIP *zipfile = openzip(fname); - - if(!zipfile) return 1; - - // find first bin or smd - while((zipentry = readzip(zipfile)) != 0) - { - char *ext; - if(strlen(zipentry->name) < 5) continue; - ext = zipentry->name+strlen(zipentry->name)-4; - - if(!strcasecmp(ext, ".bin") || !strcasecmp(ext, ".smd") || !strcasecmp(ext, ".gen")) break; - } - - if(!zipentry) { - closezip(zipfile); - return 4; // no roms - } - - size = zipentry->uncompressed_size; - - size=(size+3)&~3; // Round up to a multiple of 4 - - // Allocate space for the rom plus padding - rom=PicoCartAlloc(size); - if (rom==NULL) { closezip(zipfile); return 2; } - - if(readuncompresszip(zipfile, zipentry, (char *)rom) != 0) { - free(rom); - rom = 0; - closezip(zipfile); - return 5; // unzip failed - } - - closezip(zipfile); - - // maybe we are loading MegaCD BIOS? - if (!(PicoMCD&1) && size == 0x20000 && - (!strncmp((char *)rom+0x124, "BOOT", 4) || !strncmp((char *)rom+0x128, "BOOT", 4))) { - PicoMCD |= 1; - rom = cd_realloc(rom, size); - } - - // Check for SMD: - if ((size&0x3fff)==0x200) { DecodeSmd(rom,size); size-=0x200; } // Decode and byteswap SMD - else Byteswap(rom,size); // Just byteswap - - if (prom) *prom=rom; - if (psize) *psize=size; - - return 0; -} - -#endif diff --git a/Pico/Pico.h b/Pico/Pico.h index e7dd52a..f997c5c 100644 --- a/Pico/Pico.h +++ b/Pico/Pico.h @@ -62,10 +62,24 @@ extern areaclose *areaClose; extern void (*PicoStateProgressCB)(const char *str); // Cart.c -int PicoCartLoad(FILE *f,unsigned char **prom,unsigned int *psize); +typedef enum +{ + PMT_UNCOMPRESSED = 0, + PMT_ZIP +} pm_type; +typedef struct +{ + void *file; /* file handle */ + void *param; /* additional file related field */ + unsigned int size; /* size */ + pm_type type; +} pm_file; +pm_file *pm_open(const char *path); +size_t pm_read(void *ptr, size_t bytes, pm_file *stream); +int pm_seek(pm_file *stream, long offset, int whence); +int pm_close(pm_file *fp); +int PicoCartLoad(pm_file *f,unsigned char **prom,unsigned int *psize); int PicoCartInsert(unsigned char *rom,unsigned int romsize); -// notaz -int CartLoadZip(const char *fname, unsigned char **prom, unsigned int *psize); void Byteswap(unsigned char *data,int len); // anotherguest int PicoUnloadCart(unsigned char* romdata); diff --git a/Pico/PicoInt.h b/Pico/PicoInt.h index 0b06756..832664d 100644 --- a/Pico/PicoInt.h +++ b/Pico/PicoInt.h @@ -257,7 +257,7 @@ void z80_write(unsigned char data, unsigned short a); void z80_write16(unsigned short data, unsigned short a); // cd/Memory.c -void PicoMemSetupCD(); +void PicoMemSetupCD(void); unsigned char PicoReadCD8 (unsigned int a); unsigned short PicoReadCD16(unsigned int a); unsigned int PicoReadCD32(unsigned int a); diff --git a/Pico/cd/Area.c b/Pico/cd/Area.c index 51da616..bfc1ffa 100644 --- a/Pico/cd/Area.c +++ b/Pico/cd/Area.c @@ -243,7 +243,8 @@ int PicoCdLoadState(void *file) /* after load events */ if (Pico_mcd->s68k_regs[3]&4) // 1M mode? wram_2M_to_1M(Pico_mcd->word_ram2M); - mp3_start_play(Pico_mcd->TOC.Tracks[Pico_mcd->m.audio_track].F, Pico_mcd->m.audio_offset); + if (Pico_mcd->m.audio_track > 0 && Pico_mcd->m.audio_track < Pico_mcd->TOC.Last_Track) + mp3_start_play(Pico_mcd->TOC.Tracks[Pico_mcd->m.audio_track].F, Pico_mcd->m.audio_offset); // restore hint vector *(unsigned short *)(Pico_mcd->bios + 0x72) = Pico_mcd->m.hint_vector; diff --git a/Pico/cd/cd_file.c b/Pico/cd/cd_file.c index 0614140..a827a0c 100644 --- a/Pico/cd/cd_file.c +++ b/Pico/cd/cd_file.c @@ -16,11 +16,10 @@ void FILE_End(void) int Load_ISO(const char *iso_name, int is_bin) { - struct stat file_stat; int i, j, num_track, Cur_LBA, index, ret, iso_name_len; _scd_track *Tracks = Pico_mcd->TOC.Tracks; - FILE *tmp_file; char tmp_name[1024], tmp_ext[10]; + pm_file *pmf; static char *exts[] = { "%02d.mp3", " %02d.mp3", "-%02d.mp3", "_%02d.mp3", " - %02d.mp3", "%d.mp3", " %d.mp3", "-%d.mp3", "_%d.mp3", " - %d.mp3", @@ -33,16 +32,7 @@ int Load_ISO(const char *iso_name, int is_bin) Tracks[0].ftype = is_bin ? TYPE_BIN : TYPE_ISO; - ret = stat(iso_name, &file_stat); - if (ret != 0) return -1; - - Tracks[0].Length = file_stat.st_size; - - if (Tracks[0].ftype == TYPE_ISO) Tracks[0].Length >>= 11; // size in sectors - else Tracks[0].Length /= 2352; // size in sectors - - - Tracks[0].F = fopen(iso_name, "rb"); + Tracks[0].F = pmf = pm_open(iso_name); if (Tracks[0].F == NULL) { Tracks[0].ftype = 0; @@ -50,11 +40,9 @@ int Load_ISO(const char *iso_name, int is_bin) return -1; } - if (Tracks[0].ftype == TYPE_ISO) fseek(Tracks[0].F, 0x100, SEEK_SET); - else fseek(Tracks[0].F, 0x110, SEEK_SET); - - // fread(buf, 1, 0x200, Tracks[0].F); - fseek(Tracks[0].F, 0, SEEK_SET); + if (Tracks[0].ftype == TYPE_ISO) + Tracks[0].Length = pmf->size >>= 11; // size in sectors + else Tracks[0].Length = pmf->size /= 2352; Tracks[0].MSF.M = 0; // minutes Tracks[0].MSF.S = 2; // seconds @@ -64,7 +52,6 @@ int Load_ISO(const char *iso_name, int is_bin) Cur_LBA = Tracks[0].Length; // Size in sectors - strcpy(tmp_name, iso_name); iso_name_len = strlen(iso_name); for (num_track = 2, i = 0; i < 100; i++) @@ -72,6 +59,7 @@ int Load_ISO(const char *iso_name, int is_bin) for(j = 0; j < sizeof(exts)/sizeof(char *); j++) { int ext_len; + FILE *tmp_file; sprintf(tmp_ext, exts[j], i); ext_len = strlen(tmp_ext); @@ -88,8 +76,8 @@ int Load_ISO(const char *iso_name, int is_bin) if (tmp_file) { - // float fs; int fs; + struct stat file_stat; index = num_track - 1; ret = stat(tmp_name, &file_stat); @@ -143,13 +131,13 @@ void Unload_ISO(void) if (Pico_mcd == NULL) return; - for(i = 0; i < 100; i++) + if (Pico_mcd->TOC.Tracks[0].F) pm_close(Pico_mcd->TOC.Tracks[0].F); + + for(i = 1; i < 100; i++) { if (Pico_mcd->TOC.Tracks[i].F) fclose(Pico_mcd->TOC.Tracks[i].F); - Pico_mcd->TOC.Tracks[i].F = NULL; - Pico_mcd->TOC.Tracks[i].Length = 0; - Pico_mcd->TOC.Tracks[i].ftype = 0; } + memset(Pico_mcd->TOC.Tracks, 0, sizeof(Pico_mcd->TOC.Tracks)); } @@ -208,11 +196,11 @@ int FILE_Read_One_LBA_CDC(void) Pico_mcd->cdc.WA.N = (Pico_mcd->cdc.WA.N + 2352) & 0x7FFF; // add one sector to WA Pico_mcd->cdc.PT.N = (Pico_mcd->cdc.PT.N + 2352) & 0x7FFF; - memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N], &Pico_mcd->cdc.HEAD, 4); + *(unsigned int *)(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N) = Pico_mcd->cdc.HEAD.N; //memcpy(&Pico_mcd->cdc.Buffer[Pico_mcd->cdc.PT.N + 4], cp_buf, 2048); - fseek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET); - fread(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 1, 2048, Pico_mcd->TOC.Tracks[0].F); + pm_seek(Pico_mcd->TOC.Tracks[0].F, where_read, SEEK_SET); + pm_read(Pico_mcd->cdc.Buffer + Pico_mcd->cdc.PT.N + 4, 2048, Pico_mcd->TOC.Tracks[0].F); #ifdef DEBUG_CD cdprintf("Read -> WA = %d Buffer[%d] =", Pico_mcd->cdc.WA.N, Pico_mcd->cdc.PT.N & 0x3FFF); diff --git a/Pico/cd/cd_sys.h b/Pico/cd/cd_sys.h index f7be7d5..a71f5d2 100644 --- a/Pico/cd/cd_sys.h +++ b/Pico/cd/cd_sys.h @@ -3,8 +3,6 @@ #include "cd_file.h" -#include // FILE - #ifdef __cplusplus extern "C" { #endif @@ -37,7 +35,7 @@ typedef struct _msf MSF; // char ftype; // TYPE_ISO, TYPE_BIN, TYPE_MP3 - FILE *F; + void *F; int Length; short KBtps; // kbytes per sec for mp3s (bitrate / 1000 / 8) short pad; @@ -94,9 +92,6 @@ int Open_Tray_CDD_cD(void); int CDD_Def(void); -//void Write_CD_Audio(short *Buf, int rate, int channel, int lenght); -//void Update_CD_Audio(int **Buf, int lenght); - #ifdef __cplusplus }; diff --git a/platform/gp2x/Makefile b/platform/gp2x/Makefile index a3c6961..081715a 100644 --- a/platform/gp2x/Makefile +++ b/platform/gp2x/Makefile @@ -68,7 +68,7 @@ OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2 OBJS += ../../zlib/gzio.o ../../zlib/inffast.o ../../zlib/inflate.o ../../zlib/inftrees.o ../../zlib/trees.o \ ../../zlib/deflate.o ../../zlib/crc32.o ../../zlib/adler32.o ../../zlib/zutil.o ../../zlib/compress.o # unzip -OBJS += ../../unzip/unzip.o +OBJS += ../../unzip/unzip.o ../../unzip/unzip_stream.o # mp3 OBJS += mp3.o # CPU cores diff --git a/platform/gp2x/emu.c b/platform/gp2x/emu.c index c8c4f8a..3d6cd3a 100644 --- a/platform/gp2x/emu.c +++ b/platform/gp2x/emu.c @@ -169,31 +169,31 @@ int find_bios(int region, char **bios_file) /* checks if romFileName points to valid MegaCD image * if so, checks for suitable BIOS */ -static int cd_check(char *ext, char **bios_file) +static int cd_check(char **bios_file) { unsigned char buf[32]; - FILE *cd_f; + pm_file *cd_f; int type = 0, region = 4; // 1: Japan, 4: US, 8: Europe - cd_f = fopen(romFileName, "rb"); + cd_f = pm_open(romFileName); if (!cd_f) return 0; // let the upper level handle this - if (fread(buf, 1, 32, cd_f) != 32) { - fclose(cd_f); + if (pm_read(buf, 32, cd_f) != 32) { + pm_close(cd_f); return 0; } if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x00, 14)) type = 1; // Sega CD (ISO) if (!strncasecmp("SEGADISCSYSTEM", (char *)buf+0x10, 14)) type = 2; // Sega CD (BIN) if (type == 0) { - fclose(cd_f); + pm_close(cd_f); return 0; } /* it seems we have a CD image here. Try to detect region and load a suitable BIOS now.. */ - fseek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); - fread(buf, 1, 1, cd_f); - fclose(cd_f); + pm_seek(cd_f, (type == 1) ? 0x100+0x10B : 0x110+0x10B, SEEK_SET); + pm_read(buf, 1, cd_f); + pm_close(cd_f); if (buf[0] == 0x64) region = 8; // EU if (buf[0] == 0xa1) region = 1; // JAP @@ -217,7 +217,7 @@ int emu_ReloadRom(void) unsigned int rom_size = 0; char *used_rom_name = romFileName; char ext[5]; - FILE *rom; + pm_file *rom; int ret, cd_state; printf("emu_ReloadRom(%s)\n", romFileName); @@ -284,7 +284,7 @@ int emu_ReloadRom(void) } // check for MegaCD image - cd_state = cd_check(ext, &used_rom_name); + cd_state = cd_check(&used_rom_name); if (cd_state > 0) { PicoMCD |= 1; get_ext(used_rom_name, ext); @@ -296,7 +296,7 @@ int emu_ReloadRom(void) PicoMCD &= ~1; } - rom = fopen(used_rom_name, "rb"); + rom = pm_open(used_rom_name); if(!rom) { sprintf(menuErrorMsg, "Failed to open rom."); return 0; @@ -308,25 +308,13 @@ int emu_ReloadRom(void) rom_size = 0; } - // zipfile support - if(!strcasecmp(ext, ".zip")) { - fclose(rom); - ret = CartLoadZip(used_rom_name, &rom_data, &rom_size); - if(ret) { - if (ret == 4) strcpy(menuErrorMsg, "No ROMs found in zip."); - else sprintf(menuErrorMsg, "Unzip failed with code %i", ret); - printf("%s\n", menuErrorMsg); - return 0; - } - } else { - if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { - sprintf(menuErrorMsg, "PicoCartLoad() failed."); - printf("%s\n", menuErrorMsg); - fclose(rom); - return 0; - } - fclose(rom); + if( (ret = PicoCartLoad(rom, &rom_data, &rom_size)) ) { + sprintf(menuErrorMsg, "PicoCartLoad() failed."); + printf("%s\n", menuErrorMsg); + pm_close(rom); + return 0; } + pm_close(rom); // detect wrong files (Pico crashes on very small files), also see if ROM EP is good if(rom_size <= 0x200 || strncmp((char *)rom_data, "Pico", 4) == 0 || diff --git a/platform/gp2x/menu.c b/platform/gp2x/menu.c index 032616a..40eee48 100644 --- a/platform/gp2x/menu.c +++ b/platform/gp2x/menu.c @@ -407,7 +407,7 @@ static void draw_patchlist(int sel) if (pos < 0) continue; if (pos > 23) break; gp2x_smalltext8_lim(14, pos*10, PicoPatches[i].active ? "ON " : "OFF", 3); - gp2x_smalltext8_lim(14+6*4, pos*10, PicoPatches[i].name, 53-5); + gp2x_smalltext8_lim(14+6*4, pos*10, PicoPatches[i].name, 53-6); } pos = start + i; if (pos < 24) gp2x_smalltext8_lim(14, pos*10, "done", 4); diff --git a/platform/linux/Makefile b/platform/linux/Makefile index fc5ff06..cd18159 100644 --- a/platform/linux/Makefile +++ b/platform/linux/Makefile @@ -39,7 +39,7 @@ OBJS += ../../Pico/sound/sound.o ../../Pico/sound/sn76496.o ../../Pico/sound/ym2 OBJS += ../../zlib/gzio.o ../../zlib/inffast.o ../../zlib/inflate.o ../../zlib/inftrees.o ../../zlib/trees.o \ ../../zlib/deflate.o ../../zlib/crc32.o ../../zlib/adler32.o ../../zlib/zutil.o ../../zlib/compress.o # unzip -OBJS += ../../unzip/unzip.o +OBJS += ../../unzip/unzip.o ../../unzip/unzip_stream.o # mp3 OBJS += ../gp2x/mp3.o # CPU cores diff --git a/platform/linux/gp2x.c b/platform/linux/gp2x.c index e4e3421..cc4db98 100644 --- a/platform/linux/gp2x.c +++ b/platform/linux/gp2x.c @@ -164,6 +164,7 @@ void gp2x_init(void) printf("entering init()\n"); fflush(stdout); gp2x_screen = malloc(320*240*2 + 320*2); + memset(gp2x_screen, 0, 320*240*2 + 320*2); // snd mixerdev = open("/dev/mixer", O_RDWR); diff --git a/unzip/unzip.c b/unzip/unzip.c index 4f1786c..c055969 100644 --- a/unzip/unzip.c +++ b/unzip/unzip.c @@ -25,13 +25,9 @@ // notaz -#ifdef __DEBUG_PRINT -void dprintf(char *format, ...); -#define logerror dprintf -void errormsg(const char* extmsg, const char* usermsg, const char* zipname) -{ - dprintf("Error in zipfile %s: %s", zipname, extmsg); -} +#if 1 //def __DEBUG_PRINT +#define logerror printf +#define errormsg(str1,def,fname) printf("%s: " #def ": " str1 "\n", fname); #else #define logerror(x...) #define errormsg(x...) diff --git a/unzip/unzip.h b/unzip/unzip.h index d44f963..8d15d05 100644 --- a/unzip/unzip.h +++ b/unzip/unzip.h @@ -127,6 +127,8 @@ int readcompresszip(ZIP* zip, struct zipent* ent, char* data); */ int readuncompresszip(ZIP* zip, struct zipent* ent, char* data); +int seekcompresszip(ZIP* zip, struct zipent* ent); + /* public functions */ int /* error */ load_zipped_file (const char *zipfile, const char *filename, unsigned char **buf, unsigned int *length); diff --git a/unzip/unzip_stream.c b/unzip/unzip_stream.c new file mode 100644 index 0000000..3e7919b --- /dev/null +++ b/unzip/unzip_stream.c @@ -0,0 +1,182 @@ +/* seekable zip */ + +#include "unzip.h" + +#include +#include +#include + +#ifdef __SYMBIAN32__ +#include +#else +#include "zlib/zlib.h" +#endif + + +#define errormsg(str1,def,fname) printf("%s: " #def ": " str1 "\n", fname); + + +/* from gzio.c . Be careful with binary compatibility */ +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ +} gz_stream; + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) + +int destroy OF((gz_stream *s)); + + +gzFile zip2gz(ZIP* zip, struct zipent* ent) +{ + int err; + gz_stream *s; + const char *path; + int transparent = 0; + uInt len; + + if (!zip || !ent) + return NULL; + + /* zip stuff */ + if (ent->compression_method == 0x0000) + { + /* file is not compressed, simply stored */ + + /* check if size are equal */ + if (ent->compressed_size != ent->uncompressed_size) { + errormsg("Wrong uncompressed size in store compression", ERROR_CORRUPT,zip->zip); + return NULL; + } + + transparent = 1; + } + else if (ent->compression_method == 0x0008) + { + /* file is compressed using "Deflate" method */ + if (ent->version_needed_to_extract > 0x14) { + errormsg("Version too new", ERROR_UNSUPPORTED,zip->zip); + return NULL; + } + + if (ent->os_needed_to_extract != 0x00) { + errormsg("OS not supported", ERROR_UNSUPPORTED,zip->zip); + return NULL; + } + + if (ent->disk_number_start != zip->number_of_this_disk) { + errormsg("Cannot span disks", ERROR_UNSUPPORTED,zip->zip); + return NULL; + } + + } else { + errormsg("Compression method unsupported", ERROR_UNSUPPORTED, zip->zip); + return NULL; + } + + /* seek to compressed data */ + if (seekcompresszip(zip,ent) != 0) { + return NULL; + } + + path = zip->zip; + + /* normal gzip init for read */ + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = transparent; + s->mode = 'r'; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* windowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = zip->fp; + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + + /* check_header(s); */ + errno = 0; + len = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + return destroy(s), (gzFile)Z_NULL; + } + + s->start = ftell(s->file) - s->stream.avail_in; + + return (gzFile)s; +} + + +int gzerror2(gzFile file) +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) + return Z_STREAM_ERROR; + + return s->z_err; +} + + diff --git a/unzip/unzip_stream.h b/unzip/unzip_stream.h new file mode 100644 index 0000000..59ff2fa --- /dev/null +++ b/unzip/unzip_stream.h @@ -0,0 +1,4 @@ + +gzFile zip2gz(ZIP* zip, struct zipent* ent); +int gzerror2(gzFile file); + diff --git a/zlib/gzio.c b/zlib/gzio.c index 7e90f49..02a0a01 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -77,7 +77,8 @@ local gzFile gz_open OF((const char *path, const char *mode, int fd)); local int do_flush OF((gzFile file, int flush)); local int get_byte OF((gz_stream *s)); local void check_header OF((gz_stream *s)); -local int destroy OF((gz_stream *s)); +//local + int destroy OF((gz_stream *s)); local void putLong OF((FILE *file, uLong x)); local uLong getLong OF((gz_stream *s)); @@ -352,7 +353,8 @@ local void check_header(s) * Cleanup then free the given gz_stream. Return a zlib error code. Try freeing in the reverse order of allocations. */ -local int destroy (s) +//local +int destroy (s) gz_stream *s; { int err = Z_OK; -- 2.39.2