removing now unneeded dir from package
[drnoksnes] / loadzip.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
12  * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13  * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14  * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
21  * Permission to use, copy, modify and distribute Snes9x in both binary and
22  * source form, for non-commercial purposes, is hereby granted without fee,
23  * providing that this license information and copyright notice appear with
24  * all copies and any derived work.
25  *
26  * This software is provided 'as-is', without any express or implied
27  * warranty. In no event shall the authors be held liable for any damages
28  * arising from the use of this software.
29  *
30  * Snes9x is freeware for PERSONAL USE only. Commercial users should
31  * seek permission of the copyright holders first. Commercial use includes
32  * charging money for Snes9x or software derived from Snes9x.
33  *
34  * The copyright holders request that bug fixes and improvements to the code
35  * should be forwarded to them so everyone can benefit from the modifications
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41  
42 #include "port.h"
43
44 #ifdef UNZIP_SUPPORT
45 /**********************************************************************************************/
46 /* Loadzip.CPP                                                                                */
47 /* This file contains a function for loading a SNES ROM image from a zip file                 */
48 /**********************************************************************************************/
49
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <ctype.h>
54 #include <assert.h>
55
56 #include "snes9x.h"
57
58 #ifndef NO_INLINE_SET_GET
59 #define NO_INLINE_SET_GET
60 #endif
61
62 #include "memmap.h"
63 #include "unzip.h"
64
65 bool8 LoadZip(const char* zipname,
66               int32 *TotalFileSize,
67               int32 *headers)
68 {
69     *TotalFileSize = 0;
70     *headers = 0;
71     
72     unzFile file = unzOpen(zipname);
73     if(file == NULL)
74                 return FALSE;
75
76     // find largest file in zip file (under MAX_ROM_SIZE)
77     // or a file with extension .1
78     char filename[132];
79     int filesize = 0;
80     int port = unzGoToFirstFile(file);
81     unz_file_info info;
82     while (port == UNZ_OK)
83     {
84                 char name[132];
85                 unzGetCurrentFileInfo(file, &info, name,128, NULL,0, NULL,0);
86
87 #if 0
88                 int calc_size = info.uncompressed_size / 0x2000;
89                 calc_size *= 0x2000;
90                 if(!(info.uncompressed_size - calc_size == 512 || info.uncompressed_size == calc_size))
91                 {
92                         port = unzGoToNextFile(file);
93                         continue;
94                 }
95 #endif
96
97                 if(info.uncompressed_size > (CMemory::MAX_ROM_SIZE + 512))
98                 {
99                         port = unzGoToNextFile(file);
100                         continue;
101                 }
102
103                 if ((int) info.uncompressed_size > filesize)
104                 {
105                         strcpy(filename,name);
106                         filesize = info.uncompressed_size;
107                 }
108
109                 int len = strlen(name);
110                 if(name[len-2] == '.' && name[len-1] == '1')
111                 {
112                         strcpy(filename,name);
113                         filesize = info.uncompressed_size;
114                         break;
115                 }
116
117                 port = unzGoToNextFile(file);
118     }
119         if( !(port == UNZ_END_OF_LIST_OF_FILE || port == UNZ_OK) || filesize == 0)
120         {
121                 unzClose(file);
122                 return FALSE;
123         }
124
125         // Find extension
126         char tmp[2] = { '\0', '\0' };
127         char *ext = strrchr(filename, '.');
128         if (ext) ext++;
129         else ext = tmp;
130
131     uint8 *ptr = Memory.ROM;
132     bool8 more = FALSE;
133
134     unzLocateFile(file,filename,1);
135     unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0);
136
137     if( unzOpenCurrentFile(file) != UNZ_OK )
138     {
139                 unzClose(file);
140                 return FALSE;
141     }
142
143     do
144     {
145                 int FileSize = info.uncompressed_size;
146                 assert(FileSize <= CMemory::MAX_ROM_SIZE + 512);
147
148                 int calc_size = FileSize / 0x2000;
149                 calc_size *= 0x2000;
150
151                 int l = unzReadCurrentFile(file,ptr,FileSize);
152                 if(unzCloseCurrentFile(file) == UNZ_CRCERROR)
153                 {
154                         unzClose(file);
155                         return FALSE;
156                 }
157
158                 if (l <= 0 || l != FileSize)
159                 {
160                         unzClose(file);
161                         switch(l)
162                         {
163                         case UNZ_ERRNO:
164                                 break;
165                         case UNZ_EOF:
166                                 break;
167                         case UNZ_PARAMERROR:
168                                 break;
169                         case UNZ_BADZIPFILE:
170                                 break;
171                         case UNZ_INTERNALERROR:
172                                 break;
173                         case UNZ_CRCERROR:
174                                 break;
175                         }
176                         return FALSE;
177                 }
178
179                 if ((FileSize - calc_size == 512 && !Settings.ForceNoHeader) ||
180                         Settings.ForceHeader)
181                 {
182                         memmove (ptr, ptr + 512, calc_size);
183                         (*headers)++;
184                         FileSize -= 512;
185                 }
186                 ptr += FileSize;
187                 (*TotalFileSize) += FileSize;
188
189                 int len;
190                 if (ptr - Memory.ROM < CMemory::MAX_ROM_SIZE + 0x200 &&
191                         (isdigit (ext [0]) && ext [1] == 0 && ext [0] < '9'))
192                 {
193                         more = TRUE;
194                         ext [0]++;
195                 }
196                 else if (ptr - Memory.ROM < CMemory::MAX_ROM_SIZE + 0x200 &&
197                          (((len = strlen (filename)) == 7 || len == 8) &&
198                           strncasecmp (filename, "sf", 2) == 0 &&
199                           isdigit (filename [2]) && isdigit (filename [3]) && isdigit (filename [4]) &&
200                           isdigit (filename [5]) && isalpha (filename [len - 1])))
201                 {
202                         more = TRUE;
203                         filename [len - 1]++;
204                 }
205                 else
206                         more = FALSE;
207         
208                 if(more)
209                 {
210                         if (unzLocateFile(file,filename,1) != UNZ_OK ||
211                                 unzGetCurrentFileInfo(file, &info, filename,128, NULL,0, NULL,0) != UNZ_OK ||
212                                 unzOpenCurrentFile(file) != UNZ_OK)
213                                         break;
214                 }
215         
216     } while(more);
217     
218     unzClose(file);
219         return TRUE;
220 }
221 #endif