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