// license:BSD-3-Clause // copyright-holders:Curt Coder /********************************************************************* cbm_crt.c Commodore C64 cartridge images *********************************************************************/ #include "cbm_crt.h" //************************************************************************** // MACROS/CONSTANTS //************************************************************************** #define LOG 0 // slot names for the C64 cartridge types static const char * CRT_C64_SLOT_NAMES[_CRT_C64_COUNT] = { "standard", UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, "simons_basic", "ocean", UNSUPPORTED, "fun_play", "super_games", UNSUPPORTED, "epyxfastload", "westermann", "rex", UNSUPPORTED, "magic_formel", "system3", "warp_speed", "dinamic", "zaxxon", "magic_desk", UNSUPPORTED, "comal80", "struct_basic", "ross", "ep64", "ep7x8", "dela_ep256", "rex_ep256", "mikroasm", UNSUPPORTED, UNSUPPORTED, "stardos", UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, "ieee488", UNSUPPORTED, UNSUPPORTED, "exos", UNSUPPORTED, UNSUPPORTED, UNSUPPORTED, "super_explode", UNSUPPORTED, UNSUPPORTED, "mach5", UNSUPPORTED, "pagefox", UNSUPPORTED, "silverrock" }; //************************************************************************** // IMPLEMENTATION //************************************************************************** //------------------------------------------------- // cbm_crt_get_card - get slot interface card //------------------------------------------------- void cbm_crt_get_card(astring &result, core_file *file) { // read the header cbm_crt_header header; core_fread(file, &header, CRT_HEADER_LENGTH); if (memcmp(header.signature, CRT_SIGNATURE, 16) == 0) { UINT16 hardware = pick_integer_be(header.hardware, 0, 2); result.cpy(CRT_C64_SLOT_NAMES[hardware]); return; } result.reset(); } //------------------------------------------------- // cbm_crt_read_header - read cartridge header //------------------------------------------------- bool cbm_crt_read_header(core_file* file, size_t *roml_size, size_t *romh_size, int *exrom, int *game) { // read the header cbm_crt_header header; core_fread(file, &header, CRT_HEADER_LENGTH); if (memcmp(header.signature, CRT_SIGNATURE, 16) != 0) return false; UINT16 hardware = pick_integer_be(header.hardware, 0, 2); *exrom = header.exrom; *game = header.game; if (LOG) { logerror("Name: %s\n", header.name); logerror("Hardware: %04x\n", hardware); logerror("Slot device: %s\n", CRT_C64_SLOT_NAMES[hardware]); logerror("EXROM: %u\n", header.exrom); logerror("GAME: %u\n", header.game); } // determine ROM region lengths while (!core_feof(file)) { cbm_crt_chip chip; core_fread(file, &chip, CRT_CHIP_LENGTH); UINT16 address = pick_integer_be(chip.start_address, 0, 2); UINT16 size = pick_integer_be(chip.image_size, 0, 2); UINT16 type = pick_integer_be(chip.chip_type, 0, 2); if (LOG) { logerror("CHIP Address: %04x\n", address); logerror("CHIP Size: %04x\n", size); logerror("CHIP Type: %04x\n", type); } switch (address) { case 0x8000: *roml_size += size; break; case 0xa000: *romh_size += size; break; case 0xe000: *romh_size += size; break; default: logerror("Invalid CHIP loading address!\n"); break; } core_fseek(file, size, SEEK_CUR); } return true; } //------------------------------------------------- // cbm_crt_read_data - read cartridge data //------------------------------------------------- bool cbm_crt_read_data(core_file* file, UINT8 *roml, UINT8 *romh) { offs_t roml_offset = 0; offs_t romh_offset = 0; core_fseek(file, CRT_HEADER_LENGTH, SEEK_SET); while (!core_feof(file)) { cbm_crt_chip chip; core_fread(file, &chip, CRT_CHIP_LENGTH); UINT16 address = pick_integer_be(chip.start_address, 0, 2); UINT16 size = pick_integer_be(chip.image_size, 0, 2); switch (address) { case 0x8000: core_fread(file, roml + roml_offset, size); roml_offset += size; break; case 0xa000: core_fread(file, romh + romh_offset, size); romh_offset += size; break; case 0xe000: core_fread(file, romh + romh_offset, size); romh_offset += size; break; } } return true; }