Browse Source

support for zipped ISOs

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@65 be3aeb3a-fb24-0410-a615-afba39da0efa
notaz 17 years ago
parent
commit
83bd0b76ab
17 changed files with 413 additions and 156 deletions
  1. 12 8
      Pico/Area.c
  2. 149 69
      Pico/Cart.c
  3. 17 3
      Pico/Pico.h
  4. 1 1
      Pico/PicoInt.h
  5. 2 1
      Pico/cd/Area.c
  6. 14 26
      Pico/cd/cd_file.c
  7. 1 6
      Pico/cd/cd_sys.h
  8. 1 1
      platform/gp2x/Makefile
  9. 18 30
      platform/gp2x/emu.c
  10. 1 1
      platform/gp2x/menu.c
  11. 1 1
      platform/linux/Makefile
  12. 1 0
      platform/linux/gp2x.c
  13. 3 7
      unzip/unzip.c
  14. 2 0
      unzip/unzip.h
  15. 182 0
      unzip/unzip_stream.c
  16. 4 0
      unzip/unzip_stream.h
  17. 4 2
      zlib/gzio.c

+ 12 - 8
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;
 }

+ 149 - 69
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

+ 17 - 3
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);

+ 1 - 1
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);

+ 2 - 1
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;
 

+ 14 - 26
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);

+ 1 - 6
Pico/cd/cd_sys.h

@@ -3,8 +3,6 @@
 
 #include "cd_file.h"
 
-#include <stdio.h> // 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
 };

+ 1 - 1
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

+ 18 - 30
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 ||

+ 1 - 1
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);

+ 1 - 1
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

+ 1 - 0
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);

+ 3 - 7
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...)

+ 2 - 0
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);

+ 182 - 0
unzip/unzip_stream.c

@@ -0,0 +1,182 @@
+/* seekable zip */
+
+#include "unzip.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef __SYMBIAN32__
+#include <ezlib.h>
+#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;
+}
+
+

+ 4 - 0
unzip/unzip_stream.h

@@ -0,0 +1,4 @@
+
+gzFile zip2gz(ZIP* zip, struct zipent* ent);
+int gzerror2(gzFile file);
+

+ 4 - 2
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;