home *** CD-ROM | disk | FTP | other *** search
- /*
- * gbe - gameboy emulator
- * Copyright (C) 1999 Chuck Mason, Steven Fuller
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * Chuck Mason <chuckjr@sinclair.net>
- * Steven Fuller <relnev@atdot.org>
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h> /* 092299 */
-
- #ifdef WIN32
- # define PATH_SEPARATOR '\\'
- #else
- # define PATH_SEPARATOR '/'
- #endif
-
- #include "rom.h"
- #include "mem.h"
- #include "data.h"
-
- unsigned char color_gameboy = 0;
- unsigned char *cartridge_rom = (char *)NULL;
- unsigned char *cartridge_ram = (char *)NULL;
- char *cartridge_fname = (char *)NULL;
-
- cartsize cartridge_size = SIZE_Unknown;
- carttype cartridge_type = TYPE_Unknown;
- mbc1type cartridge_mbc1 = MBC1_Unused;
- ramsize cartridge_ramsize = SIZE_Unknown;
-
- int load_rom(char *filename)
- {
- FILE *fp;
- unsigned long file_length;
- char *ptr;
-
- if((fp = fopen(filename, "r")) == NULL)
- return 0;
-
- if((ptr = (char *)strrchr(filename, '.')) != NULL) {
- char *ptr2;
-
-
- if((ptr2 = (char *)strrchr(filename, PATH_SEPARATOR)) != NULL) {
- *ptr = '\0';
- ptr2++;
- cartridge_fname = (char *)strdup(ptr2);
- } else {
- *ptr = '\0';
- cartridge_fname = (char *)strdup(filename);
- }
- *ptr = '.';
- } else
- cartridge_fname = (char *)strdup(filename);
-
- fseek(fp, 0, SEEK_END);
-
- file_length = ftell(fp);
- rewind(fp);
-
- cartridge_rom = (char *)malloc(file_length);
-
- fread((char *)cartridge_rom, file_length, 1, fp);
- fclose(fp);
-
- printf("Cartridge Name: [");
- fwrite((char *)&cartridge_rom[0x134], 0x0F, 1, stdout);
- printf("]\n");
-
- if(cartridge_rom[0x143] == 0x80)
- color_gameboy = 1;
-
- if(force_system == REGULAR)
- color_gameboy = 0;
- else if(force_system == COLOR)
- color_gameboy = 1;
-
- if(color_gameboy) {
- printf("Color gameboy support is very preliminary.\n");
- }
-
- printf("Cart Type: ");
- switch(cartridge_rom[0x147]) {
- case 0x00:
- printf("ROM Only\n");
- cartridge_type = TYPE_ROM_Only;
- break;
- case 0x01: /* MBC1 used */
- printf("ROM+MBC1\n");
- cartridge_type = TYPE_ROM_MBC1;
- cartridge_mbc1 = MBC1_16M_8K; /* Defaults .. */
- break;
- case 0x02:
- printf("ROM+MBC1+RAM\n");
- cartridge_type = TYPE_ROM_MBC1_RAM;
- cartridge_mbc1 = MBC1_16M_8K;
- break;
- case 0x03:
- printf("ROM+MBC1+RAM+BATTERY\n");
- cartridge_type = TYPE_ROM_MBC1_RAM_BATTERY;
- cartridge_mbc1 = MBC1_16M_8K;
- break;
- case 0x05:
- printf("ROM+MBC2\n");
- cartridge_type = TYPE_ROM_MBC2;
- cartridge_ramsize = RAM_SIZE_2KB; /* really 256 bytes */
- break;
- case 0x06:
- printf("ROM+MBC2+BATTERY\n");
- cartridge_type = TYPE_ROM_MBC2_BATTERY;
- cartridge_ramsize = RAM_SIZE_2KB;
- break;
- case 0x11:
- printf("ROM+MBC3\n");
- cartridge_type = TYPE_ROM_MBC3;
- break;
- case 0x12:
- printf("ROM+MBC3+RAM\n");
- cartridge_type = TYPE_ROM_MBC3_RAM;
- break;
- case 0x13:
- printf("ROM+MBC3+RAM+BATTERY\n");
- cartridge_type = TYPE_ROM_MBC3_RAM_BATTERY;
- break;
- case 0x19:
- printf("ROM+MBC5\n");
- cartridge_type = TYPE_ROM_MBC5;
- break;
- case 0x1A:
- printf("ROM+MBC5+RAM\n");
- cartridge_type = TYPE_ROM_MBC5_RAM;
- break;
- case 0x1B:
- printf("ROM+MBC5+RAM+BATTERY\n");
- cartridge_type = TYPE_ROM_MBC5_RAM_BATTERY;
- break;
- default:
- printf("Unknown!\n");
- cartridge_type = TYPE_Unknown;
- break;
- }
-
- if(cartridge_type == TYPE_Unknown) {
- printf("Error! Unknown cartridge type %d!\n", cartridge_rom[0x147]);
- return 0;
- }
-
- printf("Cart Size: ");
- switch(cartridge_rom[0x148]) {
- case 0x00:
- printf("32K\n");
- cartridge_size = SIZE_32k;
- break;
- case 0x01:
- printf("64K\n");
- cartridge_size = SIZE_64k; /* This one's got 4 */
- break;
- case 0x02:
- printf("128K\n");
- cartridge_size = SIZE_128k; /* This rom has 8 16 banks */
- break;
- case 0x03:
- printf("256K\n");
- cartridge_size = SIZE_256k; /* This one's got 16 */
- break;
- case 0x04:
- printf("512K\n");
- cartridge_size = SIZE_512k;
- break;
- case 0x05:
- printf("1MB\n");
- cartridge_size = SIZE_1M;
- break;
- case 0x06:
- printf("2MB\n");
- cartridge_size = SIZE_2M;
- break;
- default:
- cartridge_size = SIZE_Unknown;
- printf("Unknown\n");
- }
-
- if(cartridge_size == SIZE_Unknown) {
- printf("Error! Unknown cartridge size!\n");
- return 0;
- }
-
- if(cartridge_rom[0x149] != 0x00) {
- printf("Ram Size: ");
- switch(cartridge_rom[0x149]) {
- case RAM_SIZE_2KB:
- printf("2 KB\n");
- cartridge_ramsize = RAM_SIZE_2KB;
- break;
- case RAM_SIZE_8KB:
- printf("8 KB\n");
- cartridge_ramsize = RAM_SIZE_8KB;
- break;
- case RAM_SIZE_32KB:
- printf("32 KB\n");
- cartridge_ramsize = RAM_SIZE_32KB;
- break;
- default:
- printf("Unknown (%d)\n", cartridge_rom[0x149]);
- cartridge_ramsize = SIZE_Unknown;
- break;
- }
- if(cartridge_ramsize == SIZE_Unknown) {
- printf("Error! Unknown ram size!\n");
- return 0;
- }
- }
-
- install_rom();
- install_ram();
-
- return 1;
- }
-
- void free_rom()
- {
- if(cartridge_rom)
- free(cartridge_rom);
-
- rom_save_ram();
- if(cartridge_ram)
- free(cartridge_ram);
-
- if(cartridge_fname)
- free(cartridge_fname);
-
- cartridge_type = TYPE_Unknown;
- cartridge_size = cartridge_ramsize = SIZE_Unknown;
- color_gameboy = 0;
- cartridge_rom = (char *)NULL;
- cartridge_ram = (char *)NULL;
- cartridge_fname= (char *)NULL;
-
- }
-
- void install_rom()
- {
- int i;
-
- switch(cartridge_size) {
- case SIZE_32k:
- for(i = 0; i < 8; i++)
- install_memory(i, cartridge_rom + (i * 0x1000));
- break;
- case SIZE_64k:
- case SIZE_128k:
- case SIZE_256k:
- case SIZE_512k: /* All these get bank 0 to $0-$3fff and 1 to $4000-$7fff */
- case SIZE_1M:
- case SIZE_2M:
- rom_select_bank(0, 0);
- rom_select_bank(1, 4);
- break;
- default:
- return;
- }
- }
-
- void install_ram()
- {
- if(cartridge_ramsize == SIZE_Unknown)
- return;
-
- switch(cartridge_ramsize) {
- case RAM_SIZE_8KB:
- cartridge_ram = (char *)malloc(0x2000);
- break;
- case RAM_SIZE_2KB:
- cartridge_ram = (char *)malloc(0x800);
- break;
- case RAM_SIZE_32KB:
- cartridge_ram = (char *)malloc(0x2000 * 4);
- break;
- case RAM_SIZE_128KB:
- cartridge_ram = (char *)malloc(0x2000 * 16);
- break;
- default:
- return;
- }
- rom_load_ram();
- rom_select_ram_bank(0);
- }
-
- void rom_select_bank(int bank, int wbank)
- {
- unsigned long b;
- int i;
- unsigned char *rptr;
-
- switch(cartridge_size) {
- case SIZE_32k:
- return;
- case SIZE_64k: /* banks 0 - 3 */
- if(bank >= 4)
- return;
- break;
- case SIZE_128k: /* banks 0 - 7 */
- if(bank >= 8)
- return;
- break;
- case SIZE_256k: /* banks 0 - 15 */
- if(bank >= 16)
- return;
- break;
- case SIZE_512k: /* banks 0 - 31 */
- if(bank >= 32)
- return;
- break;
- case SIZE_1M:
- if(bank >= 64)
- return;
- break;
- case SIZE_2M:
- if(bank >= 128)
- return;
- break;
- default:
- return;
- }
-
- b = (bank) * 0x4000;
- rptr = &cartridge_rom[b];
-
- for(i = 0; i < 4; i++) {
- install_memory(i + wbank, rptr + (i * 0x1000));
- }
- }
-
- void rom_select_ram_bank(int bank)
- {
- unsigned long b;
- int i;
-
- if(cartridge_ramsize == SIZE_Unknown)
- return;
-
- b = bank * 0x2000;
-
- if(cartridge_ramsize == RAM_SIZE_2KB) {
- install_memory(0x0A, cartridge_ram);
- install_memory(0x0B, (char *)NULL);
- return;
- }
-
- for(i = 0; i < 2; i++) {
- install_memory(0x0A + (i & 0x0F), cartridge_ram + (i * 0x1000) + b);
- }
- }
-
- void rom_create_sav_path(char *path)
- {
- const char *GBEDIR = ".gbesav";
- char *var;
-
-
- if(!(var = getenv("HOME"))) {
- if(!(var = getenv("USER"))) {
- sprintf(path, ".%c", PATH_SEPARATOR);
- return;
- } else {
- sprintf(path, "/home/%s/%s/", var, GBEDIR);
- }
- } else {
- sprintf(path, "%s/%s/", var, GBEDIR);
- }
- return;
- }
-
- void rom_save_ram()
- {
- char filename[512];
- FILE *fptr;
-
- /* Note all all these have 2 things in common:
- RAM and BATTERY ..
- */
- switch(cartridge_type) {
- case TYPE_ROM_MBC1_RAM_BATTERY:
- case TYPE_ROM_MBC2_BATTERY: /* MBC2 has ram in it */
- case TYPE_ROM_MBC3_RAM_BATTERY:
- case TYPE_ROM_MBC5_RAM_BATTERY:
- break;
- default:
- return;
- }
-
- rom_create_sav_path(filename);
-
- strcat(filename, cartridge_fname);
- strcat(filename, ".sav");
-
- if((fptr = fopen(filename, "w")) == NULL) {
- printf("unable to open %s for saving\n", filename);
- return;
- }
-
- switch(cartridge_ramsize) {
- case RAM_SIZE_2KB:
- fwrite(cartridge_ram, 0x400, 2, fptr);
- break;
- case RAM_SIZE_8KB:
- fwrite(cartridge_ram, 0x400, 8, fptr);
- break;
- case RAM_SIZE_32KB:
- fwrite(cartridge_ram, 0x400, 32, fptr);
- break;
- case RAM_SIZE_128KB:
- fwrite(cartridge_ram, 0x400, 128, fptr);
- break;
- }
-
- printf("saveram successfully saved to %s\n", filename);
-
- fflush(fptr);
- fclose(fptr);
- return;
- }
-
- void rom_load_ram()
- {
- char filename[512];
- FILE *fptr;
-
- switch(cartridge_type) {
- case TYPE_ROM_MBC1_RAM_BATTERY:
- case TYPE_ROM_MBC2_BATTERY:
- case TYPE_ROM_MBC3_RAM_BATTERY:
- case TYPE_ROM_MBC5_RAM_BATTERY:
- break;
- default:
- return;
- }
-
- rom_create_sav_path(filename);
-
- strcat(filename, cartridge_fname);
- strcat(filename, ".sav");
-
- if((fptr = fopen(filename, "r")) == NULL) {
- printf("unable to open %s for saving\n", filename);
- return;
- }
-
- switch(cartridge_ramsize) {
- case RAM_SIZE_2KB:
- fread(cartridge_ram, 0x400, 2, fptr);
- break;
- case RAM_SIZE_8KB:
- fread(cartridge_ram, 0x400, 8, fptr);
- break;
- case RAM_SIZE_32KB:
- fread(cartridge_ram, 0x400, 32, fptr);
- break;
- case RAM_SIZE_128KB:
- fread(cartridge_ram, 0x400, 128, fptr);
- break;
- }
-
- printf("saveram successfully read from %s\n", filename);
-
- fflush(fptr);
- fclose(fptr);
- return;
- }
-