romload.c
来自「DGen源码最后版本」· C语言 代码 · 共 267 行
C
267 行
// DGen project v1.11+
// Module for loading in the different rom image types (.bin/.smd)
// --------------------------------
// Notes from Alex...
// 1) In load_zip_into, in an effort to have DGen
// create a save file that matches what's INSIDE a zip, it strcpys
// the inside-zip name over the *name coming in. Unfortunately there is
// no checking as to whether the *name buffer is big enough :(
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ZIP_SUPPORT
#ifdef ZIP_SUPPORT
#include "unzip.h"
#endif
extern int dprintf(char *format, ...);
int load_bin_into(char *name, unsigned char **into, int *file_size)
{
FILE *hand=NULL;
unsigned char *tempPtr = NULL;
*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);
tempPtr = (unsigned char *)malloc(*file_size);
if (tempPtr==NULL) return *file_size;
*into = tempPtr;
fread(tempPtr,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
int deinterleve(unsigned char **into, int *file_size)
{
// unsigned char head[512]={0};
int chunk_count=0,file_chunks=0;
unsigned char *chunk_buf=NULL;
unsigned char *fromPtr = NULL, *toPtr = NULL;
int got_to=0,i;
file_chunks=((*file_size-512)/16384);
// Make sure the parser ignores the last 512 bytes that will be left over.
*file_size = file_chunks*16384;
chunk_count=file_chunks;
chunk_buf=malloc(16384);
if (chunk_buf==NULL)
{dprintf ("out of mem\n"); return -1;}
fromPtr = *into + 512; // SMD's have a 512 Header we need to ignore...
toPtr = *into;
for (got_to=0,i=0; i<chunk_count; i++,got_to+=16384)
{
int j;
// Deinterleave each chunk
memcpy (chunk_buf, &fromPtr[got_to], 16384);
for (j=0;j<8192;j++)
toPtr[got_to+(j<<1)+1]=chunk_buf[j];
for (j=0;j<8192;j++)
toPtr[got_to+(j<<1)+0]=chunk_buf[j+8192];
}
free(chunk_buf);
return 0;
}
#ifdef ZIP_SUPPORT
// ---------------------------------------------------------------------------
// -- Load Zip
// ---------------------------------------------------------------------------
load_zip_into(char *name, unsigned char **into, int *file_size)
{
char filename[132];
char zname[132];
char *tempPtr = NULL;
int filesize = 0;
int port = 0;
int len = 0;
int l = 0;
unz_file_info info;
unzFile file = unzOpen(name);
if (file == NULL)
{
dprintf ("Zip Error: unzOpen(%s) failed\n",name);
return 0;
}
// find largest file in zip file (under MAX_ROM_SIZE)
// or a file with extension .bin, or .smd
port = unzGoToFirstFile(file);
// Find SMD or BIN
while(port == UNZ_OK)
{
unzGetCurrentFileInfo(file, &info, zname, 128, NULL,0, NULL,0);
len = strlen(zname);
// If SMD or BIN found
if ((!strnicmp(&zname[len-4], ".SMD", 4)) || (!strnicmp(&zname[len-4], ".BIN", 4)) )
{
strcpy(filename,zname);
filesize = info.uncompressed_size;
break;
}
// Goto Next File
port = unzGoToNextFile(file);
}
// If none found, close the zip and get out of here
if( !(port == UNZ_END_OF_LIST_OF_FILE || port == UNZ_OK) || filesize == 0)
{
dprintf ("Zip Error: file contains no .smd or .bin\n");
unzClose(file);
return 0;
}
if (unzLocateFile(file, zname, 1) != UNZ_OK )
{
dprintf ("Zip Error: unzLocateFile() failed\n");
unzClose(file);
return 0;
}
unzGetCurrentFileInfo(file, &info, zname, 128, NULL,0, NULL,0);
// Open the file found
if( unzOpenCurrentFile(file) != UNZ_OK )
{
unzClose(file);
dprintf("Error in zip file\n");
return 0;
}
*file_size = info.uncompressed_size;
tempPtr = (unsigned char *)malloc(*file_size);
if (tempPtr==NULL) return *file_size;
*into = tempPtr;
// Load the file
l = unzReadCurrentFile(file, tempPtr,*file_size);
if(unzCloseCurrentFile(file) == UNZ_CRCERROR)
{
unzClose(file);
dprintf("CRC error in zip file.\n");
return 0;
}
else
// Make sure the name used for the save is the one INSIDE the zip
strcpy(name, zname);
if(l <= 0 || l != *file_size)
{
unzClose(file);
dprintf("Error in zip file.\n");
switch(l)
{
case UNZ_ERRNO:
dprintf("Errno:...\n");
break;
case UNZ_EOF:
dprintf("Unexpected end of file.\n");
break;
case UNZ_PARAMERROR:
dprintf("Parameter error.\n");
break;
case UNZ_BADZIPFILE:
dprintf("Bad zipfile.\n");
break;
case UNZ_INTERNALERROR:
dprintf("Internal error.\n");
break;
case UNZ_CRCERROR:
dprintf("CRC error.\n");
break;
}
return 0;
}
unzClose(file);
return -1;
}
#endif
// 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 **rombuffer, int *file_size)
{
int format=0; // bin 0, smd 1
int len;
if (name==NULL) return -1;
len=strlen(name);
#ifdef ZIP_SUPPORT
// If it's a zip... then LoadZip
if (!strnicmp( &name[len-4], ".ZIP", 4))
load_zip_into(name, &(*rombuffer), file_size);
else
#endif
{
if (load_bin_into(name, &(*rombuffer), file_size)!=0)
{
dprintf ("Error: Could not load '%s'\n",name);
}
}
// RE-CHECK the length of the rom to detect if load_zip_into changed the name (and gave us the type)
len=strlen(name);
if (!strnicmp( &name[len-4], ".SMD", 4))
deinterleve( &(*rombuffer), file_size);
return -1;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?