1 /*
2  * gbsplay is a Gameboy sound player
3  *
4  * 2003-2006,2013 (C) by Tobias Diedrich <ranma+gbsplay@tdiedrich.de>
5  *                       Christian Garbs <mitch@cgarbs.de>
6  * Licensed under GNU GPL v1 or, at your option, any later version.
7  */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <unistd.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <ctype.h>
18 
19 #include "common.h"
20 #include "gbhw.h"
21 #include "gbcpu.h"
22 #include "gbs.h"
23 #include "crc32.h"
24 
25 #define GBS_MAGIC		"GBS"
26 #define GBS_EXTHDR_MAGIC	"GBSX"
27 #define GBR_MAGIC		"GBRF"
28 
29 const char *boot_rom_file = ".dmg_rom.bin";
30 
gbs_init(struct gbs * gbs,long subsong)31 regparm long gbs_init(struct gbs *gbs, long subsong)
32 {
33 	gbhw_init(gbs->rom, gbs->romsize);
34 
35 	if (subsong == -1) subsong = gbs->defaultsong - 1;
36 	if (subsong >= gbs->songs) {
37 		fprintf(stderr, _("Subsong number out of range (min=0, max=%d).\n"), (int)gbs->songs - 1);
38 		return 0;
39 	}
40 
41 	if (gbs->defaultbank != 1) {
42 		gbcpu_mem_put(0x2000, gbs->defaultbank);
43 	}
44 	gbhw_io_put(0xff06, gbs->tma);
45 	gbhw_io_put(0xff07, gbs->tac);
46 	gbhw_io_put(0xffff, 0x05);
47 
48 	REGS16_W(gbcpu_regs, SP, gbs->stack);
49 
50 	/* put halt breakpoint PC on stack */
51 	gbcpu_halt_at_pc = 0xffff;
52 	REGS16_W(gbcpu_regs, PC, 0xff80);
53 	REGS16_W(gbcpu_regs, HL, gbcpu_halt_at_pc);
54 	gbcpu_mem_put(0xff80, 0xe5); /* push hl */
55 	gbcpu_step();
56 	/* clear regs/memory touched by stack etup */
57 	REGS16_W(gbcpu_regs, HL, 0x0000);
58 	gbcpu_mem_put(0xff80, 0x00);
59 
60 	REGS16_W(gbcpu_regs, PC, gbs->init);
61 	gbcpu_regs.rn.a = subsong;
62 
63 	gbs->ticks = 0;
64 	gbs->subsong = subsong;
65 
66 	return 1;
67 }
68 
gbs_set_nextsubsong_cb(struct gbs * gbs,gbs_nextsubsong_cb cb,void * priv)69 regparm void gbs_set_nextsubsong_cb(struct gbs *gbs, gbs_nextsubsong_cb cb, void *priv)
70 {
71 	gbs->nextsubsong_cb = cb;
72 	gbs->nextsubsong_cb_priv = priv;
73 }
74 
gbs_nextsubsong(struct gbs * gbs)75 static regparm long gbs_nextsubsong(struct gbs *gbs)
76 {
77 	if (gbs->nextsubsong_cb != NULL) {
78 		return gbs->nextsubsong_cb(gbs, gbs->nextsubsong_cb_priv);
79 	} else {
80 		gbs->subsong++;
81 		if (gbs->subsong >= gbs->songs)
82 			return false;
83 		gbs_init(gbs, gbs->subsong);
84 	}
85 	return true;
86 }
87 
gbs_step(struct gbs * gbs,long time_to_work)88 regparm long gbs_step(struct gbs *gbs, long time_to_work)
89 {
90 	long cycles = gbhw_step(time_to_work);
91 	long time;
92 
93 	if (cycles < 0) {
94 		return false;
95 	}
96 
97 	gbs->ticks += cycles;
98 
99 	gbhw_getminmax(&gbs->lmin, &gbs->lmax, &gbs->rmin, &gbs->rmax);
100 	gbs->lvol = -gbs->lmin > gbs->lmax ? -gbs->lmin : gbs->lmax;
101 	gbs->rvol = -gbs->rmin > gbs->rmax ? -gbs->rmin : gbs->rmax;
102 
103 	time = gbs->ticks / GBHW_CLOCK;
104 	if (gbs->silence_timeout) {
105 		if (gbs->lmin == gbs->lmax && gbs->rmin == gbs->rmax) {
106 			if (gbs->silence_start == 0)
107 				gbs->silence_start = gbs->ticks;
108 		} else gbs->silence_start = 0;
109 	}
110 
111 	if (gbs->fadeout && gbs->subsong_timeout &&
112 	    time >= gbs->subsong_timeout - gbs->fadeout - gbs->gap)
113 		gbhw_master_fade(128/gbs->fadeout, 0);
114 	if (gbs->subsong_timeout &&
115 	    time >= gbs->subsong_timeout - gbs->gap)
116 		gbhw_master_fade(128*16, 0);
117 
118 	if (gbs->silence_start &&
119 	    (gbs->ticks - gbs->silence_start) / GBHW_CLOCK >= gbs->silence_timeout) {
120 		if (gbs->subsong_info[gbs->subsong].len == 0) {
121 			gbs->subsong_info[gbs->subsong].len = gbs->ticks * GBS_LEN_DIV / GBHW_CLOCK;
122 		}
123 		return gbs_nextsubsong(gbs);
124 	}
125 	if (gbs->subsong_timeout && time >= gbs->subsong_timeout)
126 		return gbs_nextsubsong(gbs);
127 
128 	return true;
129 }
130 
gbs_printinfo(struct gbs * gbs,long verbose)131 regparm void gbs_printinfo(struct gbs *gbs, long verbose)
132 {
133 	printf(_("GBSVersion:       %u\n"
134 	         "Title:            \"%s\"\n"
135 	         "Author:           \"%s\"\n"
136 	         "Copyright:        \"%s\"\n"
137 	         "Load address:     0x%04x\n"
138 	         "Init address:     0x%04x\n"
139 	         "Play address:     0x%04x\n"
140 	         "Stack pointer:    0x%04x\n"
141 	         "File size:        0x%08x\n"
142 	         "ROM size:         0x%08lx (%ld banks)\n"
143 	         "Subsongs:         %u\n"
144 	         "Default subsong:  %u\n"),
145 	       gbs->version,
146 	       gbs->title,
147 	       gbs->author,
148 	       gbs->copyright,
149 	       gbs->load,
150 	       gbs->init,
151 	       gbs->play,
152 	       gbs->stack,
153 	       (unsigned int)gbs->filesize,
154 	       gbs->romsize,
155 	       gbs->romsize/0x4000,
156 	       gbs->songs,
157 	       gbs->defaultsong);
158 	if (gbs->tac & 0x04) {
159 		long timertc = (256-gbs->tma) * (16 << (((gbs->tac+3) & 3) << 1));
160 		if (gbs->tac & 0x80)
161 			timertc /= 2;
162 		printf(_("Timing:           %2.2fHz timer%s\n"),
163 		       GBHW_CLOCK / (float)timertc,
164 		       (gbs->tac & 0x78) == 0x40 ? _(" + VBlank (ugetab)") : "");
165 	} else {
166 		printf(_("Timing:           %s\n"),
167 		       _("59.7Hz VBlank\n"));
168 	}
169 	if (gbs->defaultbank != 1) {
170 		printf(_("Bank @0x4000:     %d\n"), gbs->defaultbank);
171 	}
172 	if (gbs->version == 2) {
173 		printf(_("CRC32:            0x%08lx/0x%08lx (%s)\n"),
174 		       (unsigned long)gbs->crc, (unsigned long)gbs->crcnow,
175 		       gbs->crc == gbs->crcnow ? _("OK") : _("Failed"));
176 	} else {
177 		printf(_("CRC32:            0x%08lx\n"),
178 		       (unsigned long)gbs->crcnow);
179 	}
180 	if (verbose && gbs->version == 2) {
181 		long i;
182 		for (i=0; i<gbs->songs; i++) {
183 			printf(_("Subsong %03ld:	"), i);
184 			if (gbs->subsong_info[i].title) {
185 				printf("\"%s\" ", gbs->subsong_info[i].title);
186 			} else {
187 				printf("%s ", _("untitled"));
188 			}
189 			if (gbs->subsong_info[i].len) {
190 				printf(_("(%ld seconds)\n"),
191 				       (long)(gbs->subsong_info[i].len >> GBS_LEN_SHIFT));
192 			} else {
193 				printf("%s\n", _("no time limit"));
194 			}
195 		}
196 	}
197 }
198 
gbs_free(struct gbs * gbs)199 static regparm void gbs_free(struct gbs *gbs)
200 {
201 	if (gbs->buf)
202 		free(gbs->buf);
203 	if (gbs->subsong_info)
204 		free(gbs->subsong_info);
205 	free(gbs);
206 }
207 
gbs_close(struct gbs * gbs)208 regparm void gbs_close(struct gbs *gbs)
209 {
210 	gbs_free(gbs);
211 }
212 
writeint(char * buf,uint32_t val,long bytes)213 static regparm void writeint(char *buf, uint32_t val, long bytes)
214 {
215 	long shift = 0;
216 	long i;
217 
218 	for (i=0; i<bytes; i++) {
219 		buf[i] = (val >> shift) & 0xff;
220 		shift += 8;
221 	}
222 }
223 
readint(char * buf,long bytes)224 static regparm uint32_t readint(char *buf, long bytes)
225 {
226 	long i;
227 	long shift = 0;
228 	uint32_t res = 0;
229 
230 	for (i=0; i<bytes; i++) {
231 		res |= (unsigned char)buf[i] << shift;
232 		shift += 8;
233 	}
234 
235 	return res;
236 }
237 
gbs_write(struct gbs * gbs,char * name,long version)238 regparm long gbs_write(struct gbs *gbs, char *name, long version)
239 {
240 	long fd;
241 	long codelen = (gbs->codelen + 15) >> 4;
242 	char pad[16];
243 	char strings[65536];
244 	long stringofs = 0;
245 	long newlen = gbs->filesize;
246 	long namelen = strlen(name);
247 	char *tmpname = malloc(namelen + sizeof(".tmp\0"));
248 
249 	memcpy(tmpname, name, namelen);
250 	sprintf(&tmpname[namelen], ".tmp");
251 	memset(pad, 0xff, sizeof(pad));
252 
253 	if ((fd = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) {
254 		fprintf(stderr, _("Could not open %s: %s\n"), name, strerror(errno));
255 		return 0;
256 	}
257 
258 	if (version == 2) {
259 		long len,i;
260 		long ehdrlen = 32 + 8*gbs->songs;
261 		uint32_t hdrcrc;
262 
263 		newlen = 0x70 + codelen*16 + ehdrlen;
264 		gbs->buf[3] = 1;
265 		gbs->buf = realloc(gbs->buf, newlen + 65536);
266 		gbs->code = gbs->buf + 0x70;
267 		gbs->exthdr = gbs->code + codelen*16;
268 		writeint(gbs->buf + 0x6e, codelen, 2);
269 		memset(&gbs->code[gbs->codelen], 0x00, codelen*16 - gbs->codelen);
270 		memset(gbs->exthdr, 0x00, ehdrlen + 65536);
271 		memcpy(gbs->exthdr, GBS_EXTHDR_MAGIC, strlen(GBS_EXTHDR_MAGIC));
272 		gbs->exthdr[0x1c] = gbs->songs;
273 		if ((len = strlen(gbs->title)) > 32) {
274 			memcpy(strings+stringofs, gbs->title, len+1);
275 			writeint(&gbs->exthdr[0x14], stringofs, 2);
276 			stringofs += len+1;
277 		} else writeint(&gbs->exthdr[0x14], 0xffff, 2);
278 		if ((len = strlen(gbs->author)) > 32) {
279 			memcpy(strings+stringofs, gbs->author, len+1);
280 			writeint(&gbs->exthdr[0x16], stringofs, 2);
281 			stringofs += len+1;
282 		} else writeint(&gbs->exthdr[0x16], 0xffff, 2);
283 		if ((len = strlen(gbs->copyright)) > 30) {
284 			memcpy(strings+stringofs, gbs->copyright, len+1);
285 			writeint(&gbs->exthdr[0x18], stringofs, 2);
286 			stringofs += len+1;
287 		} else writeint(&gbs->exthdr[0x18], 0xffff, 2);
288 
289 		for (i=0; i<gbs->songs; i++) {
290 			writeint(&gbs->exthdr[0x20+8*i],
291 			         gbs->subsong_info[i].len, 4);
292 			if (gbs->subsong_info[i].title &&
293 			    strcmp(gbs->subsong_info[i].title, "") != 0) {
294 				len = strlen(gbs->subsong_info[i].title)+1;
295 				memcpy(strings+stringofs, gbs->subsong_info[i].title, len);
296 				writeint(&gbs->exthdr[0x20+8*i+4],
297 				         stringofs, 2);
298 				stringofs += len;
299 			} else writeint(&gbs->exthdr[0x20+8*i+4], 0xffff, 2);
300 		}
301 		memcpy(gbs->buf + newlen, strings, stringofs);
302 		newlen += stringofs;
303 
304 		writeint(&gbs->exthdr[0x04], ehdrlen+stringofs-8, 4);
305 		writeint(&gbs->exthdr[0x0c], gbs->filesize, 4);
306 		gbs->crc = gbs_crc32(0, gbs->buf, gbs->filesize);
307 		writeint(&gbs->exthdr[0x10], gbs->crc, 4);
308 		hdrcrc = gbs_crc32(0, gbs->exthdr, ehdrlen+stringofs);
309 		writeint(&gbs->exthdr[0x08], hdrcrc, 4);
310 
311 	} else {
312 		if (gbs->version == 2) {
313 			gbs->buf[3] = 1;
314 		}
315 	}
316 	if (write(fd, gbs->buf, newlen) == newlen) {
317 		int ret = 1;
318 		close(fd);
319 		if (rename(tmpname, name) == -1) {
320 			fprintf(stderr, _("Could not rename %s to %s: %s\n"), tmpname, name, strerror(errno));
321 			ret = 0;
322 		}
323 		return ret;
324 	}
325 	close(fd);
326 
327 	return 1;
328 }
329 
gb_open(char * name)330 static regparm struct gbs *gb_open(char *name)
331 {
332 	long fd, i, name_len;
333 	struct stat st;
334 	struct gbs *gbs = malloc(sizeof(struct gbs));
335 	char *buf, *bootname;
336 	uint8_t bootrom[256];
337 	char *na_str = _("gb / not available");
338 
339 	memset(gbs, 0, sizeof(struct gbs));
340 	gbs->silence_timeout = 2*60;
341 	gbs->subsong_timeout = 2*60;
342 	gbs->gap = 2;
343 	gbs->fadeout = 3;
344 	if ((fd = open(name, O_RDONLY)) == -1) {
345 		fprintf(stderr, _("Could not open %s: %s\n"), name, strerror(errno));
346 		gbs_free(gbs);
347 		return NULL;
348 	}
349 	fstat(fd, &st);
350 	gbs->buf = buf = malloc(st.st_size);
351 	if (read(fd, buf, st.st_size) != st.st_size) {
352 		fprintf(stderr, _("Could not read %s: %s\n"), name, strerror(errno));
353 		gbs_free(gbs);
354 		return NULL;
355 	}
356 	gbs->version = 0;
357 	gbs->songs = 1;
358 	gbs->defaultsong = 1;
359 	gbs->defaultbank = 1;
360 	gbs->load  = 0;
361 	gbs->init  = 0x100;
362 	gbs->play = gbs->init;
363 	gbs->stack = 0xfffe;
364 
365 	/* For accuracy testing purposes, support boot rom. */
366 	name_len = strlen(getenv("HOME")) + strlen(boot_rom_file) + 2;
367 	bootname = malloc(name_len);
368 	snprintf(bootname, name_len, "%s/%s", getenv("HOME"), boot_rom_file);
369 	if ((fd = open(bootname, O_RDONLY)) != -1) {
370 		if (read(fd, bootrom, sizeof(bootrom)) == sizeof(bootrom)) {
371 			gbhw_enable_bootrom(bootrom);
372 			gbs->init = 0;
373 		}
374 	}
375 	free(bootname);
376 
377 	/* Test if this looks like a valid rom header title */
378 	for (i=0x0134; i<0x0143; i++) {
379 		if (!(isalnum(buf[i]) || isspace(buf[i])))
380 			break;
381 	}
382 	if (buf[i] == 0) {
383 		/* Title looks valid and is zero-terminated. */
384 		gbs->title = &buf[0x0134];
385 	} else {
386 		gbs->title = na_str;
387 	}
388 	gbs->author = na_str;
389 	gbs->copyright = na_str;
390 	gbs->code = buf;
391 	gbs->filesize = st.st_size;
392 
393 	gbs->subsong_info = malloc(gbs->songs * sizeof(struct gbs_subsong_info));
394 	memset(gbs->subsong_info, 0, gbs->songs * sizeof(struct gbs_subsong_info));
395 	gbs->codelen = st.st_size - 0x20;
396 	gbs->crcnow = gbs_crc32(0, buf, gbs->filesize);
397 	gbs->romsize = (gbs->codelen + 0x3fff) & ~0x3fff;
398 
399 	gbs->rom = calloc(1, gbs->romsize);
400 	memcpy(gbs->rom, buf, gbs->codelen);
401 
402 	close(fd);
403 
404 	return gbs;
405 }
406 
gbr_open(char * name)407 static regparm struct gbs *gbr_open(char *name)
408 {
409 	long fd, i;
410 	struct stat st;
411 	struct gbs *gbs = malloc(sizeof(struct gbs));
412 	char *buf;
413 	char *na_str = _("gbr / not available");
414 	uint16_t vsync_addr;
415 	uint16_t timer_addr;
416 
417 	memset(gbs, 0, sizeof(struct gbs));
418 	gbs->silence_timeout = 2;
419 	gbs->subsong_timeout = 2*60;
420 	gbs->gap = 2;
421 	gbs->fadeout = 3;
422 	if ((fd = open(name, O_RDONLY)) == -1) {
423 		fprintf(stderr, _("Could not open %s: %s\n"), name, strerror(errno));
424 		gbs_free(gbs);
425 		return NULL;
426 	}
427 	fstat(fd, &st);
428 	gbs->buf = buf = malloc(st.st_size);
429 	if (read(fd, buf, st.st_size) != st.st_size) {
430 		fprintf(stderr, _("Could not read %s: %s\n"), name, strerror(errno));
431 		gbs_free(gbs);
432 		return NULL;
433 	}
434 	if (strncmp(buf, GBR_MAGIC, 4) != 0) {
435 		fprintf(stderr, _("Not a GBR-File: %s\n"), name);
436 		gbs_free(gbs);
437 		return NULL;
438 	}
439 	if (buf[0x05] != 0) {
440 		fprintf(stderr, _("Unsupported default bank @0x0000: %d\n"), buf[0x05]);
441 		gbs_free(gbs);
442 		return NULL;
443 	}
444 	if (buf[0x07] < 1 || buf[0x07] > 3) {
445 		fprintf(stderr, _("Unsupported timerflag value: %d\n"), buf[0x07]);
446 		gbs_free(gbs);
447 		return NULL;
448 	}
449 	gbs->version = 0;
450 	gbs->songs = 255;
451 	gbs->defaultsong = 1;
452 	gbs->defaultbank = buf[0x06];
453 	gbs->load  = 0;
454 	gbs->init  = readint(&buf[0x08], 2);
455 	vsync_addr = readint(&buf[0x0a], 2);
456 	timer_addr = readint(&buf[0x0c], 2);
457 
458 	if (buf[0x07] == 1) {
459 		gbs->play = vsync_addr;
460 	} else {
461 		gbs->play = timer_addr;
462 	}
463 	gbs->tma = buf[0x0e];
464 	gbs->tac = buf[0x0f];
465 	gbs->stack = 0xfffe;
466 
467 	/* Test if this looks like a valid rom header title */
468 	for (i=0x0154; i<0x0163; i++) {
469 		if (!(isalnum(buf[i]) || isspace(buf[i])))
470 			break;
471 	}
472 	if (buf[i] == 0) {
473 		/* Title looks valid and is zero-terminated. */
474 		gbs->title = &buf[0x0154];
475 	} else {
476 		gbs->title = na_str;
477 	}
478 	gbs->author = na_str;
479 	gbs->copyright = na_str;
480 	gbs->code = &buf[0x20];
481 	gbs->filesize = st.st_size;
482 
483 	gbs->subsong_info = malloc(gbs->songs * sizeof(struct gbs_subsong_info));
484 	memset(gbs->subsong_info, 0, gbs->songs * sizeof(struct gbs_subsong_info));
485 	gbs->codelen = st.st_size - 0x20;
486 	gbs->crcnow = gbs_crc32(0, buf, gbs->filesize);
487 	gbs->romsize = (gbs->codelen + 0x3fff) & ~0x3fff;
488 
489 	gbs->rom = calloc(1, gbs->romsize);
490 	memcpy(gbs->rom, &buf[0x20], gbs->codelen);
491 
492 	gbs->rom[0x40] = 0xd9; /* reti */
493 	gbs->rom[0x50] = 0xd9; /* reti */
494 	if (buf[0x07] & 1) {
495 		/* V-Blank */
496 		gbs->rom[0x40] = 0xc3; /* jp imm16 */
497 		gbs->rom[0x41] = vsync_addr & 0xff;
498 		gbs->rom[0x42] = vsync_addr >> 8;
499 	}
500 	if (buf[0x07] & 2) {
501 		/* Timer */
502 		gbs->rom[0x50] = 0xc3; /* jp imm16 */
503 		gbs->rom[0x51] = timer_addr & 0xff;
504 		gbs->rom[0x52] = timer_addr >> 8;
505 	}
506 	close(fd);
507 
508 	return gbs;
509 }
510 
gbs_open(char * name)511 regparm struct gbs *gbs_open(char *name)
512 {
513 	long fd, i;
514 	struct stat st;
515 	struct gbs *gbs = malloc(sizeof(struct gbs));
516 	char *buf;
517 	char *buf2 = NULL;
518 	long have_ehdr = 0;
519 
520 	memset(gbs, 0, sizeof(struct gbs));
521 	gbs->silence_timeout = 2;
522 	gbs->subsong_timeout = 2*60;
523 	gbs->gap = 2;
524 	gbs->fadeout = 3;
525 	gbs->defaultbank = 1;
526 	if ((fd = open(name, O_RDONLY)) == -1) {
527 		fprintf(stderr, _("Could not open %s: %s\n"), name, strerror(errno));
528 		gbs_free(gbs);
529 		return NULL;
530 	}
531 	fstat(fd, &st);
532 	gbs->buf = buf = malloc(st.st_size);
533 	if (read(fd, buf, st.st_size) != st.st_size) {
534 		fprintf(stderr, _("Could not read %s: %s\n"), name, strerror(errno));
535 		gbs_free(gbs);
536 		return NULL;
537 	}
538 	if (strncmp(buf, GBR_MAGIC, 4) == 0) {
539 		gbs_free(gbs);
540 		return gbr_open(name);
541 	}
542 	if (gbs_crc32(0, &buf[0x104], 48) == 0x46195417) {
543 		gbs_free(gbs);
544 		return gb_open(name);
545 	}
546 	if (strncmp(buf, GBS_MAGIC, 3) != 0) {
547 		fprintf(stderr, _("Not a GBS-File: %s\n"), name);
548 		gbs_free(gbs);
549 		return NULL;
550 	}
551 	gbs->version = buf[0x03];
552 	if (gbs->version != 1) {
553 		fprintf(stderr, _("GBS Version %d unsupported.\n"), gbs->version);
554 		gbs_free(gbs);
555 		return NULL;
556 	}
557 
558 	gbs->songs = buf[0x04];
559 	if (gbs->songs < 1) {
560 		fprintf(stderr, _("Number of subsongs = %d is unreasonable.\n"), gbs->songs);
561 		gbs_free(gbs);
562 		return NULL;
563 	}
564 
565 	gbs->defaultsong = buf[0x05];
566 	if (gbs->defaultsong < 1 || gbs->defaultsong > gbs->songs) {
567 		fprintf(stderr, _("Default subsong %d is out of range [1..%d].\n"), gbs->defaultsong, gbs->songs);
568 		gbs_free(gbs);
569 		return NULL;
570 	}
571 
572 	gbs->load  = readint(&buf[0x06], 2);
573 	gbs->init  = readint(&buf[0x08], 2);
574 	gbs->play  = readint(&buf[0x0a], 2);
575 	gbs->stack = readint(&buf[0x0c], 2);
576 	gbs->tma = buf[0x0e];
577 	gbs->tac = buf[0x0f];
578 
579 	memcpy(gbs->v1strings, &buf[0x10], 32);
580 	memcpy(gbs->v1strings+33, &buf[0x30], 32);
581 	memcpy(gbs->v1strings+66, &buf[0x50], 30);
582 	gbs->title = gbs->v1strings;
583 	gbs->author = gbs->v1strings+33;
584 	gbs->copyright = gbs->v1strings+66;
585 	gbs->code = &buf[0x70];
586 	gbs->filesize = st.st_size;
587 
588 	gbs->subsong_info = malloc(gbs->songs * sizeof(struct gbs_subsong_info));
589 	memset(gbs->subsong_info, 0, gbs->songs * sizeof(struct gbs_subsong_info));
590 	gbs->codelen = (buf[0x6e] + (buf[0x6f] << 8)) << 4;
591 	if ((0x70 + gbs->codelen) < (gbs->filesize - 8) &&
592 	    strncmp(&buf[0x70 + gbs->codelen], GBS_EXTHDR_MAGIC, 4) == 0) {
593 		uint32_t crc, realcrc, ehdrlen;
594 
595 		gbs->exthdr = gbs->code + gbs->codelen;
596 		ehdrlen = readint(&gbs->exthdr[0x04], 4) + 8;
597 		crc = readint(&gbs->exthdr[0x08], 4);
598 		writeint(&gbs->exthdr[0x08], 0, 4);
599 
600 		if ((realcrc=gbs_crc32(0, gbs->exthdr, ehdrlen)) == crc) {
601 			have_ehdr = 1;
602 		} else {
603 			fprintf(stderr, _("Warning: Extended header found, but CRC does not match (0x%08x != 0x%08x).\n"),
604 			        crc, realcrc);
605 		}
606 	}
607 	if (have_ehdr) {
608 		buf2 = gbs->exthdr;
609 		gbs->filesize = readint(&buf2[0x0c], 4);
610 		gbs->crc = readint(&buf2[0x10], 4);
611 		writeint(&buf2[0x10], 0, 4);
612 	} else {
613 		memcpy(gbs->v1strings+66, &buf[0x50], 32);
614 		gbs->codelen = st.st_size - 0x70;
615 	}
616 	gbs->crcnow = gbs_crc32(0, buf, gbs->filesize);
617 	if (have_ehdr) {
618 		long gbs_titleex;
619 		long gbs_authorex;
620 		long gbs_copyex;
621 		long entries;
622 
623 		gbs->version = 2;
624 		entries = buf2[0x1c];
625 		gbs->strings = gbs->exthdr + 32 + 8*entries;
626 
627 		gbs_titleex = readint(&buf2[0x14], 2);
628 		gbs_authorex = readint(&buf2[0x16], 2);
629 		gbs_copyex = readint(&buf2[0x18], 2);
630 		if (gbs_titleex != 0xffff)
631 			gbs->title = gbs->strings + gbs_titleex;
632 		if (gbs_authorex != 0xffff)
633 			gbs->author = gbs->strings + gbs_authorex;
634 		if (gbs_copyex != 0xffff)
635 			gbs->copyright = gbs->strings + gbs_copyex;
636 
637 		for (i=0; i<entries; i++) {
638 			long ofs = readint(&buf2[32 + 8*i + 4], 2);
639 			gbs->subsong_info[i].len = readint(&buf2[32 + 8*i], 4);
640 			if (ofs == 0xffff)
641 				gbs->subsong_info[i].title = NULL;
642 			else gbs->subsong_info[i].title = gbs->strings + ofs;
643 		}
644 
645 		if (gbs->crc != gbs->crcnow) {
646 			fprintf(stderr, _("Warning: File CRC does not match (0x%08x != 0x%08x).\n"),
647 			        gbs->crc, gbs->crcnow);
648 		}
649 	}
650 
651 	gbs->romsize = (gbs->codelen + gbs->load + 0x3fff) & ~0x3fff;
652 
653 	gbs->rom = calloc(1, gbs->romsize);
654 	memcpy(&gbs->rom[gbs->load], gbs->code, gbs->codelen);
655 
656 	for (i=0; i<8; i++) {
657 		long addr = gbs->load + 8*i; /* jump address */
658 		gbs->rom[8*i]   = 0xc3; /* jp imm16 */
659 		gbs->rom[8*i+1] = addr & 0xff;
660 		gbs->rom[8*i+2] = addr >> 8;
661 	}
662 	if ((gbs->tac & 0x78) == 0x40) { /* ugetab int vector extension */
663 		/* V-Blank */
664 		gbs->rom[0x40] = 0xc3; /* jp imm16 */
665 		gbs->rom[0x41] = (gbs->load + 0x40) & 0xff;
666 		gbs->rom[0x42] = (gbs->load + 0x40) >> 8;
667 		/* Timer */
668 		gbs->rom[0x50] = 0xc3; /* jp imm16 */
669 		gbs->rom[0x51] = (gbs->load + 0x48) & 0xff;
670 		gbs->rom[0x52] = (gbs->load + 0x48) >> 8;
671 	} else if (gbs->tac & 0x04) { /* timer enabled */
672 		/* V-Blank */
673 		gbs->rom[0x40] = 0xd9; /* reti */
674 		/* Timer */
675 		gbs->rom[0x50] = 0xc3; /* jp imm16 */
676 		gbs->rom[0x51] = gbs->play & 0xff;
677 		gbs->rom[0x52] = gbs->play >> 8;
678 	} else {
679 		/* V-Blank */
680 		gbs->rom[0x40] = 0xc3; /* jp imm16 */
681 		gbs->rom[0x41] = gbs->play & 0xff;
682 		gbs->rom[0x42] = gbs->play >> 8;
683 		/* Timer */
684 		gbs->rom[0x50] = 0xd9; /* reti */
685 	}
686 	gbs->rom[0x48] = 0xd9; /* reti (LCD Stat) */
687 	gbs->rom[0x58] = 0xd9; /* reti (Serial) */
688 	gbs->rom[0x60] = 0xd9; /* reti (Joypad) */
689 
690 	close(fd);
691 
692 	return gbs;
693 }
694