From 27089678282cb4ed090d11979c4ec8f7495f4a2a Mon Sep 17 00:00:00 2001 From: neonloop Date: Thu, 6 May 2021 01:09:21 +0000 Subject: Adds support for loading .zip files --- Makefile.linux | 2 +- Makefile.trimui | 2 +- gba_memory.c | 8 ++- zip.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ zip.h | 26 +++++++++ 5 files changed, 195 insertions(+), 3 deletions(-) create mode 100644 zip.c create mode 100644 zip.h diff --git a/Makefile.linux b/Makefile.linux index f39aa91..066b5b9 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -8,7 +8,7 @@ CC = $(CROSS_COMPILE)gcc SYSROOT = $(shell $(CC) --print-sysroot) -OBJS = main.o cpu.o gba_memory.o video.o input.o sound.o cheats.o cpu_threaded.o bios_data.o x86/x86_stub.o gba_cc_lut.o \ +OBJS = main.o cpu.o gba_memory.o video.o input.o sound.o cheats.o cpu_threaded.o bios_data.o zip.o x86/x86_stub.o gba_cc_lut.o \ frontend/libpicofe/input.o frontend/libpicofe/in_sdl.o frontend/libpicofe/linux/in_evdev.o frontend/libpicofe/linux/plat.o frontend/libpicofe/fonts.o frontend/libpicofe/readpng.o frontend/libpicofe/config_file.o \ frontend/config.o frontend/menu.o frontend/plat_linux.o frontend/main.o frontend/scale.o diff --git a/Makefile.trimui b/Makefile.trimui index cdbaa43..25fe88e 100644 --- a/Makefile.trimui +++ b/Makefile.trimui @@ -9,7 +9,7 @@ CC = $(CROSS_COMPILE)gcc SYSROOT = $(shell $(CC) --print-sysroot) OBJS = main.o cpu.o gba_memory.o video.o input.o sound.o gba_cc_lut.o \ - bios_data.o cheats.o arm/arm_stub.o cpu_threaded.o arm/video_blend.o \ + bios_data.o cheats.o zip.o arm/arm_stub.o cpu_threaded.o arm/video_blend.o \ frontend/libpicofe/input.o frontend/libpicofe/in_sdl.o \ frontend/libpicofe/linux/in_evdev.o frontend/libpicofe/linux/plat.o \ frontend/libpicofe/fonts.o frontend/libpicofe/readpng.o frontend/libpicofe/config_file.o \ diff --git a/gba_memory.c b/gba_memory.c index 8d94ca5..d2af846 100644 --- a/gba_memory.c +++ b/gba_memory.c @@ -18,6 +18,7 @@ */ #include "common.h" +#include "zip.h" /* Sound */ #define gbc_sound_tone_control_low(channel, address) \ @@ -2381,10 +2382,15 @@ char gamepak_filename[512]; u32 load_gamepak(const char *name) { + char *dot_position = strrchr(name, '.'); + s32 file_size; char cheats_filename[256]; char *p; - s32 file_size = load_gamepak_raw(name); + if(!strcmp(dot_position, ".zip")) + file_size = load_file_zip(name); + else + file_size = load_gamepak_raw(name); if(file_size == -1) return -1; diff --git a/zip.c b/zip.c new file mode 100644 index 0000000..d563d5f --- /dev/null +++ b/zip.c @@ -0,0 +1,160 @@ +/* gameplaySP + * + * Copyright (C) 2006 Exophase + * Copyright (C) 2006 SiberianSTAR + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include + +#define ZIP_BUFFER_SIZE (128 * 1024) + +struct SZIPFileDataDescriptor +{ + s32 CRC32; + s32 CompressedSize; + s32 UncompressedSize; +} __attribute__((packed)); + +struct SZIPFileHeader +{ + char Sig[4]; // EDIT: Used to be s32 Sig; + s16 VersionToExtract; + s16 GeneralBitFlag; + s16 CompressionMethod; + s16 LastModFileTime; + s16 LastModFileDate; + struct SZIPFileDataDescriptor DataDescriptor; + s16 FilenameLength; + s16 ExtraFieldLength; +} __attribute__((packed)); + +u32 load_file_zip(const char *filename) +{ + struct SZIPFileHeader data; + char tmp[1024]; + s32 retval = -1; + u8 *buffer = NULL; + u8 *cbuffer; + char *ext; + int ret; + FILE *fd; + + fd = fopen(filename, "rb"); + + if(!fd) + return -1; + + while (1) + { + ret = fread(&data, 1, sizeof(data), fd); + if (ret != sizeof(data)) + break; + + // It checks for the following: 0x50 0x4B 0x03 0x04 (PK..) + if( data.Sig[0] != 0x50 || data.Sig[1] != 0x4B || + data.Sig[2] != 0x03 || data.Sig[3] != 0x04 ) + { + break; + } + + ret = fread(tmp, 1, data.FilenameLength, fd); + if (ret != data.FilenameLength) + break; + + tmp[data.FilenameLength] = 0; // end string + + if(data.ExtraFieldLength) + fseek(fd, data.ExtraFieldLength, SEEK_CUR); + + if(data.GeneralBitFlag & 0x0008) + { + fread(&data.DataDescriptor, + 1, sizeof(struct SZIPFileDataDescriptor), fd); + } + + ext = strrchr(tmp, '.') + 1; + + // file is too big + if(data.DataDescriptor.UncompressedSize > gamepak_ram_buffer_size) + goto skip; + + if(!strcasecmp(ext, "bin") || !strcasecmp(ext, "gba")) + { + buffer = gamepak_rom; + + // ok, found + switch(data.CompressionMethod) + { + case 0: + retval = data.DataDescriptor.UncompressedSize; + fread(buffer, 1, retval, fd); + goto outcode; + + case 8: + { + z_stream stream; + s32 err; + + cbuffer = malloc(ZIP_BUFFER_SIZE); + + stream.next_in = (Bytef*)cbuffer; + stream.avail_in = (u32)ZIP_BUFFER_SIZE; + + stream.next_out = (Bytef*)buffer; + + // EDIT: Now uses proper conversion of data types for retval. + retval = (u32)data.DataDescriptor.UncompressedSize; + stream.avail_out = data.DataDescriptor.UncompressedSize; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit2(&stream, -MAX_WBITS); + + fread(cbuffer, 1, ZIP_BUFFER_SIZE, fd); + + if(err == Z_OK) + { + while(err != Z_STREAM_END) + { + err = inflate(&stream, Z_SYNC_FLUSH); + if(err == Z_BUF_ERROR) + { + stream.avail_in = ZIP_BUFFER_SIZE; + stream.next_in = (Bytef*)cbuffer; + fread(cbuffer, 1, ZIP_BUFFER_SIZE, fd); + } + } + err = Z_OK; + inflateEnd(&stream); + } + free(cbuffer); + goto outcode; + } + } + } + +skip: + fseek(fd, data.DataDescriptor.CompressedSize, SEEK_CUR); + } + +outcode: + fclose(fd); + + return retval; +} diff --git a/zip.h b/zip.h new file mode 100644 index 0000000..12a51ee --- /dev/null +++ b/zip.h @@ -0,0 +1,26 @@ +/* gameplaySP + * + * Copyright (C) 2006 Exophase + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ZIP_H +#define ZIP_H + +u32 load_file_zip(const char *filename); + +#endif + -- cgit v1.2.3