mirror of
https://github.com/extremscorner/not64.git
synced 2024-05-29 01:07:58 -04:00
745a66a377
Fixed copying name from ROM header. Adjusted for libogc-rice changes. Synchronized changes from Swiss.
269 lines
6.9 KiB
C
269 lines
6.9 KiB
C
/**
|
|
* Mupen64 - rom_gc.c
|
|
* Copyright (C) 2002 Hacktarux,
|
|
* Wii/GC Additional code by tehpola, emu_kidid
|
|
*
|
|
* Mupen64 homepage: http://mupen64.emulation64.com
|
|
* email address: hacktarux@yahoo.fr
|
|
*
|
|
* If you want to contribute to the project please contact
|
|
* me first (maybe someone is already making what you are
|
|
* planning to do).
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/
|
|
* or modify it under the terms of the GNU General Public Li-
|
|
* cence as published by the Free Software Foundation; either
|
|
* version 2 of the Licence, or any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be use-
|
|
* ful, but WITHOUT ANY WARRANTY; without even the implied war-
|
|
* ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public Licence for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public
|
|
* Licence along with this program; if not, write to the Free
|
|
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
|
|
* USA.
|
|
*
|
|
**/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <ogc/machine/processor.h>
|
|
#include "ROM-Cache.h"
|
|
#include "rom.h"
|
|
|
|
int rom_length;
|
|
int rom_byte_swap;
|
|
rom_header ROM_HEADER;
|
|
rom_settings ROM_SETTINGS;
|
|
|
|
int init_byte_swap(unsigned int magicWord)
|
|
{
|
|
switch (magicWord)
|
|
{
|
|
case 0x37804012: // aka byteswapped
|
|
rom_byte_swap = BYTE_SWAP_BYTE;
|
|
break;
|
|
case 0x40123780: // aka little endian, aka halfswapped
|
|
rom_byte_swap = BYTE_SWAP_HALF;
|
|
break;
|
|
case 0x80371240:
|
|
rom_byte_swap = BYTE_SWAP_NONE;
|
|
break;
|
|
default:
|
|
rom_byte_swap = BYTE_SWAP_BAD;
|
|
break;
|
|
}
|
|
|
|
return rom_byte_swap;
|
|
}
|
|
|
|
void byte_swap(char* buffer, unsigned int length)
|
|
{
|
|
int i;
|
|
|
|
if (rom_byte_swap == BYTE_SWAP_HALF) { // aka little endian (40123780) vs (80371240)
|
|
for (i = 0; i < (length & ~3); i += 4)
|
|
*(u32*)(buffer + i) = __lwbrx(buffer, i);
|
|
} else if (rom_byte_swap == BYTE_SWAP_BYTE) { // (37804012) vs (80371240)
|
|
for (i = 0; i < (length & ~3); i += 2)
|
|
*(u16*)(buffer + i) = __lhbrx(buffer, i);
|
|
}
|
|
}
|
|
|
|
void stripInvalidChars(char* str)
|
|
{
|
|
char* p;
|
|
|
|
while ((p = strpbrk(str, "\\/:*?\"<>|")) != NULL)
|
|
*p = '_';
|
|
}
|
|
|
|
static struct {
|
|
int Cartridge_ID;
|
|
char* Country_codes;
|
|
} ROM_TABLE[] = {
|
|
{ 'D3', "J", }, // Akumajou Dracula Mokushiroku - Real Action Adventure
|
|
{ 'D4', "J", }, // Akumajou Dracula Mokushiroku Gaiden - Legend of Cornell
|
|
{ 'B7', "EJPU" }, // Banjo-Tooie
|
|
{ 'GT', "J", }, // City Tour Grandprix - Zennihon GT Senshuken
|
|
{ 'FU', "EP", }, // Conker's Bad Fur Day
|
|
{ 'CW', "EP" }, // Cruis'n World
|
|
{ 'CZ', "J", }, // Custom Robo V2
|
|
{ 'D6', "J", }, // Densha de GO! 64
|
|
{ 'DO', "EJP" }, // Donkey Kong 64
|
|
{ 'D2', "J", }, // Doraemon 2 - Nobita to Hikari no Shinden
|
|
{ '3D', "J", }, // Doraemon 3 - Nobita no Machi SOS!
|
|
{ 'MX', "EJP" }, // Excitebike 64
|
|
{ 'X7', "E" }, // GoldenEye X 5d
|
|
{ 'GC', "EP" }, // GT 64 - Championship Edition
|
|
{ 'IM', "J", }, // Ide Yousuke no Mahjong Juku
|
|
{ 'K4', "EJP" }, // Kirby 64 - The Crystal Shards
|
|
{ 'NB', "EP" }, // Kobe Bryant in NBA Courtside
|
|
{ 'MV', "EJP" }, // Mario Party 3
|
|
{ 'M8', "EJP" }, // Mario Tennis
|
|
{ 'EV', "J" }, // Neon Genesis Evangelion
|
|
{ 'PP', "J" }, // Parlor! Pro 64 - Pachinko Jikki Simulation Game
|
|
{ 'UB', "J" }, // PD Ultraman Battle Collection 64
|
|
{ 'PD', "EJP" }, // Perfect Dark
|
|
{ 'R7', "J" }, // Robot Ponkottsu 64 - 7tsu no Umi no Caramel
|
|
{ 'RZ', "EP" }, // RR64 - Ridge Racer 64
|
|
{ 'EP', "EJP" }, // Star Wars Episode I - Racer
|
|
{ 'YS', "EJP" }, // Yoshi's Story
|
|
};
|
|
|
|
// Checks if the current game is in the ID list for 16kbit eeprom save type
|
|
// cause it's cheaper to have a ID list than an entire .ini file :)
|
|
bool isEEPROM16k()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < sizeof(ROM_TABLE) / sizeof(ROM_TABLE[0]); i++)
|
|
{
|
|
if (ROM_TABLE[i].Cartridge_ID == ROM_HEADER.Cartridge_ID &&
|
|
strchr(ROM_TABLE[i].Country_codes, ROM_HEADER.Country_code))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/* Loads the ROM into the ROM cache */
|
|
int rom_read(fileBrowser_file* file){
|
|
|
|
int i;
|
|
|
|
ROMCache_init(file);
|
|
int ret = ROMCache_load(file);
|
|
if(ret) {
|
|
ROMCache_deinit(file);
|
|
return ret;
|
|
}
|
|
ROMCache_read(&ROM_HEADER, 0, sizeof(rom_header));
|
|
|
|
//Copy header name as Goodname (in the .ini we can use CRC to identify ROMS)
|
|
memcpy(ROM_SETTINGS.goodname, ROM_HEADER.Name, 20);
|
|
ROM_SETTINGS.goodname[20] = '\0';
|
|
//Maximum ROM name is 20 bytes. Lets make sure we cut off trailing spaces
|
|
for(i = strlen(ROM_SETTINGS.goodname); i>0; i--)
|
|
{
|
|
if(ROM_SETTINGS.goodname[i-1] != ' ') {
|
|
ROM_SETTINGS.goodname[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
// Replace any non file system compliant chars with underscores
|
|
stripInvalidChars(&ROM_SETTINGS.goodname[0]);
|
|
// Fix save type for certain special sized (16kbit) eeprom games
|
|
ROM_SETTINGS.isEEPROM16k = isEEPROM16k();
|
|
|
|
//Set VI limit based on ROM header
|
|
InitTimer();
|
|
|
|
return ret;
|
|
}
|
|
|
|
void countrycodestring(unsigned short countrycode, char *string)
|
|
{
|
|
switch (countrycode)
|
|
{
|
|
case 0: /* Demo */
|
|
strcpy(string, ("Demo"));
|
|
break;
|
|
|
|
case '7': /* Beta */
|
|
strcpy(string, ("Beta"));
|
|
break;
|
|
|
|
case 0x41: /* Japan / USA */
|
|
strcpy(string, ("USA/Japan"));
|
|
break;
|
|
|
|
case 0x44: /* Germany */
|
|
strcpy(string, ("Germany"));
|
|
break;
|
|
|
|
case 0x45: /* USA */
|
|
strcpy(string, ("USA"));
|
|
break;
|
|
|
|
case 0x46: /* France */
|
|
strcpy(string, ("France"));
|
|
break;
|
|
|
|
case 'I': /* Italy */
|
|
strcpy(string, ("Italy"));
|
|
break;
|
|
|
|
case 0x4A: /* Japan */
|
|
strcpy(string, ("Japan"));
|
|
break;
|
|
|
|
case 'S': /* Spain */
|
|
strcpy(string, ("Spain"));
|
|
break;
|
|
|
|
case 0x55: case 0x59: /* Australia */
|
|
sprintf(string, ("Australia (0x%2.2X)"), countrycode);
|
|
break;
|
|
|
|
case 0x50: case 0x58: case 0x20:
|
|
case 0x21: case 0x38: case 0x70:
|
|
sprintf(string, ("Europe (0x%02X)"), countrycode);
|
|
break;
|
|
|
|
default:
|
|
sprintf(string, ("Unknown (0x%02X)"), countrycode);
|
|
break;
|
|
}
|
|
}
|
|
|
|
char *saveregionstr()
|
|
{
|
|
switch (ROM_HEADER.Country_code&0xFF)
|
|
{
|
|
case 0: /* Demo */
|
|
return "(Demo)";
|
|
break;
|
|
case '7': /* Beta */
|
|
return "(Beta)";
|
|
break;
|
|
case 0x41: /* Japan / USA */
|
|
return "(JU)";
|
|
break;
|
|
case 0x44: /* Germany */
|
|
return "(G)";
|
|
break;
|
|
case 0x45: /* USA */
|
|
return "(U)";
|
|
break;
|
|
case 0x46: /* France */
|
|
return "(F)";
|
|
break;
|
|
case 'I': /* Italy */
|
|
return "(I)";
|
|
break;
|
|
case 0x4A: /* Japan */
|
|
return "(J)";
|
|
break;
|
|
case 'S': /* Spain */
|
|
return "(S)";
|
|
break;
|
|
case 0x55: case 0x59: /* Australia */
|
|
return "(A)";
|
|
break;
|
|
case 0x50: case 0x58: case 0x20:
|
|
case 0x21: case 0x38: case 0x70:
|
|
return "(E)";
|
|
break;
|
|
default:
|
|
return "(Unk)";
|
|
break;
|
|
}
|
|
}
|
|
|