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 + -
显示快捷键?