BizHawk/waterbox/pizza/lib/cartridge.c

174 lines
5.0 KiB
C

/*
This file is part of Emu-Pizza
Emu-Pizza is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Emu-Pizza is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Emu-Pizza. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include "global.h"
#include "mmu.h"
#include "utils.h"
/* buffer big enough to contain the largest possible ROM */
uint8_t rom[2 << 24];
/* battery backed RAM & RTC*/
char file_sav[1024];
char file_rtc[1024];
/* guess what */
/* return values */
/* 0: OK */
/* 1: Can't open/read file */
/* 2: Unknown cartridge */
char cartridge_load(const void* data, size_t sz)
{
int i,z = 0;
if (sz < 1 || sz > 2 << 24)
return 1;
memcpy(rom, data, sz);
/* gameboy color? */
if (rom[0x143] == 0xC0 || rom[0x143] == 0x80)
{
utils_log("Gameboy Color cartridge\n");
global_cgb = 1;
}
else
{
utils_log("Gameboy Classic cartridge\n");
global_cgb = 0;
}
/* get cartridge infos */
uint8_t mbc = rom[0x147];
utils_log("Cartridge code: %02x\n", mbc);
switch (mbc)
{
case 0x00: utils_log("ROM ONLY\n"); break;
case 0x01: utils_log("MBC1\n"); break;
case 0x02: utils_log("MBC1 + RAM\n"); break;
case 0x03: utils_log("MBC1 + RAM + BATTERY\n"); break;
case 0x05: utils_log("MBC2\n"); break;
case 0x06: mmu_init_ram(512); utils_log("MBC2 + BATTERY\n"); break;
case 0x10: utils_log("MBC3 + TIMER + RAM + BATTERY\n"); break;
case 0x11: utils_log("MBC3\n"); break;
case 0x12: utils_log("MBC3 + RAM\n"); break;
case 0x13: utils_log("MBC3 + RAM + BATTERY\n"); break;
case 0x19: utils_log("MBC5\n"); break;
case 0x1A: utils_log("MBC5 + RAM\n"); break;
case 0x1B: utils_log("MBC5 + RAM + BATTERY\n"); break;
case 0x1C: global_rumble = 1;
utils_log("MBC5 + RUMBLE\n");
break;
case 0x1D: global_rumble = 1;
utils_log("MBC5 + RUMBLE + RAM\n");
break;
case 0x1E: global_rumble = 1;
utils_log("MBC5 + RUMBLE + RAM + BATTERY\n");
break;
default: utils_log("Unknown cartridge type: %02x\n", mbc);
return 2;
}
/* title */
for (i=0x134; i<0x143; i++)
if (rom[i] > 0x40 && rom[i] < 0x5B)
global_cart_name[z++] = rom[i];
global_cart_name[z] = '\0';
utils_log("%s\n", global_cart_name);
/* get ROM banks */
uint8_t byte = rom[0x148];
utils_log("ROM: ");
switch (byte)
{
case 0x00: utils_log("0 banks\n"); break;
case 0x01: utils_log("4 banks\n"); break;
case 0x02: utils_log("8 banks\n"); break;
case 0x03: utils_log("16 banks\n"); break;
case 0x04: utils_log("32 banks\n"); break;
case 0x05: utils_log("64 banks\n"); break;
case 0x06: utils_log("128 banks\n"); break;
case 0x07: utils_log("256 banks\n"); break;
case 0x52: utils_log("72 banks\n"); break;
case 0x53: utils_log("80 banks\n"); break;
case 0x54: utils_log("96 banks\n"); break;
}
/* init MMU */
mmu_init(mbc, byte);
/* get RAM banks */
byte = rom[0x149];
utils_log("RAM: ");
switch (byte)
{
case 0x00: utils_log("NO RAM\n"); break;
case 0x01: mmu_init_ram(1 << 11); utils_log("2 kB\n"); break;
case 0x02:
/* MBC5 got bigger values */
if (mbc >= 0x19 && mbc <= 0x1E)
{
mmu_init_ram(1 << 16);
utils_log("64 kB\n");
}
else
{
mmu_init_ram(1 << 13);
utils_log("8 kB\n");
}
break;
case 0x03: mmu_init_ram(1 << 15); utils_log("32 kB\n"); break;
case 0x04: mmu_init_ram(1 << 17); utils_log("128 kB\n"); break;
case 0x05: mmu_init_ram(1 << 16); utils_log("64 kB\n"); break;
}
/* restore saved RAM if it's the case */
mmu_restore_ram(file_sav);
/* restore saved RTC if it's the case */
mmu_restore_rtc(file_rtc);
/* load FULL ROM at 0x0000 address of system memory */
mmu_load_cartridge(rom, sz);
return 0;
}
void cartridge_term()
{
/* save persistent data (battery backed RAM and RTC clock) */
mmu_save_ram(file_sav);
mmu_save_rtc(file_rtc);
}