Import Debian changes 1.23-11
[debian-dgen.git] / romload.c
blob58de349f644c9cf9d5f427c3273d23265a1da27d
1 // DGen/SDL v1.15+
3 // Module for loading in the different rom image types (.bin/.smd)
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <time.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <fcntl.h>
13 #include <sys/wait.h>
15 static int load_bin_into(char *name,unsigned char *into)
17 FILE *hand=NULL;
18 int file_size=0;
20 hand=fopen(name,"rb");
21 if (hand==NULL)
22 return -1;
24 fseek(hand,0,SEEK_END);
25 file_size=ftell(hand);
26 fseek(hand,0,SEEK_SET);
27 if (into==NULL) return file_size;
29 fread(into,1,file_size,hand);
30 fclose(hand);
31 return 0;
35 WHAT YOU FIND IN THE 512 BYTES HEADER:
37 0: Number of blocks 1
38 1: H03 *
39 2: SPLIT? 2
40 8: HAA *
41 9: HBB *
42 ALL OTHER BYTES: H00
44 1: This first byte should have the number of 16KB blocks the rom has.
45 The header isn't part of the formula, so this number is:
46 [size of rom-512]/16386
47 If the size is more than 255, the value should be H00.
49 2: This byte indicates if the ROM is a part of a splitted rom series. If
50 the rom is the last part of the series (or isn't a splitted rom at all),
51 this byte should be H00. In other cases should be H40. See "CREATING
52 SPLITTED ROMS" for details on this format.
55 // 16k chunks, even bytes first then odd
57 static int load_smd_into(char *name,unsigned char *into)
59 unsigned char head[512]={0};
60 FILE *hand=NULL;
61 int chunk_count=0,file_chunks=0;
62 int file_size=0;
63 unsigned char *chunk_buf=NULL;
64 int got_to=0,i;
66 hand=fopen(name,"rb");
67 if (hand==NULL)
68 return -1;
70 fseek(hand,0,SEEK_END);
71 file_size=ftell(hand);
72 fseek(hand,0,SEEK_SET);
74 if (fread(head,1,512,hand)!=512) { fclose(hand); return -1; }
76 //chunk_count=head[0];
77 // Sometimes header is wrong apparently
79 file_chunks=((file_size-512)/16384);
81 chunk_count=file_chunks;
83 //if (chunk_count>file_chunks) chunk_count=file_chunks;
85 if (into==NULL) return (chunk_count*16384);
87 chunk_buf=malloc(16384);
88 if (chunk_buf==NULL)
89 {printf ("out of mem\n"); fclose(hand); return -1;}
91 for (got_to=0,i=0; i<chunk_count; i++,got_to+=16384)
93 int j;
94 // Deinterleave each chunk
95 fread(chunk_buf,1,16384,hand);
96 for (j=0;j<8192;j++)
97 into[got_to+(j<<1)+1]=chunk_buf[j];
98 for (j=0;j<8192;j++)
99 into[got_to+(j<<1)+0]=chunk_buf[j+8192];
101 free(chunk_buf);
103 fclose(hand);
105 return 0;
108 // If 'into' is NULL returns rom size, otherwise expect
109 // 'into' to be a buffer big enough for the rom size
110 // (i.e. pass NULL, malloc, pass pointer, emulate, free pointer)
112 int load_rom_into(char *name,unsigned char *into)
114 int format=0; // bin 0, smd 1
115 int len;
116 unsigned char magicbuf[10];
117 FILE *romfile;
118 if (name==NULL) return -1;
120 /* Open the file and get the first little shnippit of it so we can check
121 * the magic numbers on it. */
122 if(!(romfile = fopen(name, "rb"))) return -1;
123 fread(magicbuf, 10, 1, romfile);
124 fclose(romfile);
126 /* Check for the magic on various gzip-supported compressions */
127 if((magicbuf[0] == 037 && magicbuf[1] == 036) || /* compress'd (.Z) */
128 (magicbuf[0] == 037 && magicbuf[1] == 0213) || /* gzipped (.gz) */
129 (magicbuf[0] == 037 && magicbuf[1] == 0236) || /* frozen (.f,.z) */
130 (magicbuf[0] == 037 && magicbuf[1] == 0240) || /* LZH (?) */
131 (magicbuf[0] == 'P' && magicbuf[1] == 'K')) /* ZIP (.zip ;) */
133 char temp[0x100], *temp2;
134 int f;
135 /* Run it through gzip (I know this is cheap ;) */
136 asprintf(&temp2, "/tmp/dgenrom_XXXXXX");
137 f = mkstemp(temp2);
138 if (f == -1) {
139 perror("mkstemp");
140 return -1;
142 close(f);
144 f = open(name, O_RDONLY);
145 if (f == -1) {
146 perror("open");
147 return -1;
149 if (dup2(f, 0) == -1) {
150 perror("dup2");
151 return -1;
153 sprintf(temp, "zcat > %s", temp2);
154 if (system(temp)) {
155 perror("system");
156 return -1;
159 /* Recurse with the new file */
160 len = load_rom_into(temp2, into);
161 remove(temp2);
162 sync();
163 return len;
165 /* Do bzip2 also */
166 if(magicbuf[0] == 'B' && magicbuf[1] == 'Z' && magicbuf[2] == 'h')
168 char temp[0x100], *temp2;
169 int f;
170 /* Damn, this looks almost like the gzip stuff above. *lol* :) */
171 asprintf(&temp2, "/tmp/dgenrom_XXXXXX");
172 f = mkstemp(temp2);
173 if (f == -1) {
174 perror("mkstemp");
175 return -1;
177 close(f);
179 f = open(name, O_RDONLY);
180 if (f == -1) {
181 perror("open");
182 return -1;
184 if (dup2(f, 0) == -1) {
185 perror("dup2");
186 return -1;
188 sprintf(temp, "bzcat > %s", temp2);
189 if (system(temp)) {
190 perror("system");
191 return -1;
194 /* Recurse with the uncompressed file */
195 len = load_rom_into(temp2, into);
196 remove(temp2);
197 sync();
198 return len;
200 /* Next check for SMD magic */
201 if(magicbuf[8] == 0xaa && magicbuf[9] == 0xbb)
202 format = 1;
203 /* Otherwise we can only hope it's binary */
204 else format = 0;
206 switch (format)
208 case 1: return load_smd_into(name,into);
209 default: return load_bin_into(name,into);
211 return -1;