From 6b7c2af8d47cbb3c84acbc0ef8610a6b5be7691e Mon Sep 17 00:00:00 2001 From: Christopher Bonhage Date: Mon, 29 Nov 2021 13:05:55 -0500 Subject: [PATCH] Add support for 768Kbit SRAM save type Fixes a Segfault when loading Dezaemon 3D. * Unfortunately, Dezaemon 3D does not actually work yet. It appears to fail the SRAM test, which still needs further investigation. Adds an option alias for sram256k to disambiguate with new sram768k option. --- cen64.c | 14 ++++++++++++-- device/cart_db.c | 1 + device/cart_db.h | 1 + device/options.c | 26 +++++++++++++++++++++++++- device/options.h | 1 + pi/controller.c | 44 ++++++++++++++++++++++++++------------------ 6 files changed, 66 insertions(+), 21 deletions(-) diff --git a/cen64.c b/cen64.c index a9784a1..95b3816 100644 --- a/cen64.c +++ b/cen64.c @@ -140,8 +140,18 @@ int cen64_main(int argc, const char **argv) { break; case CART_DB_SAVE_TYPE_SRAM_256KBIT: if (options.sram_path == NULL) { - printf("Warning: cart saves to SRAM, but none specified (see -sram)\n"); + printf("Warning: cart saves to 256kbit SRAM, but none specified (see -sram256k)\n"); open_save_file(NULL, 0x8000, &sram, NULL); + } else if (options.sram_size != 0x8000) { + printf("Warning: cart saves to 256kbit SRAM, but different size specified (see -sram256k)\n"); + } + break; + case CART_DB_SAVE_TYPE_SRAM_768KBIT: + if (options.sram_path == NULL) { + printf("Warning: cart saves to 768kbit SRAM, but none specified (see -sram768k)\n"); + open_save_file(NULL, 0x18000, &sram, NULL); + } else if (options.sram_size != 0x18000) { + printf("Warning: cart saves to 768kbit SRAM, but different size specified (see -sram768k)\n"); } break; } @@ -159,7 +169,7 @@ int cen64_main(int argc, const char **argv) { } if (options.sram_path != NULL && - open_save_file(options.sram_path, 0x8000, &sram, NULL)) { + open_save_file(options.sram_path, options.sram_size, &sram, NULL)) { cen64_alloc_cleanup(); return EXIT_FAILURE; } diff --git a/device/cart_db.c b/device/cart_db.c index bb822ee..cbf42a9 100644 --- a/device/cart_db.c +++ b/device/cart_db.c @@ -18,6 +18,7 @@ static const struct cart_db_entry cart_db_table[] = { + {"CDZ", "J", CART_DB_SAVE_TYPE_SRAM_768KBIT, "Dezaemon 3D"}, {"CFZ", "EJ", CART_DB_SAVE_TYPE_SRAM_256KBIT, "F-Zero X (NTSC)"}, {"CLB", "EJ", CART_DB_SAVE_TYPE_EEPROM_4KBIT, "Mario Party (NTSC)"}, {"CP2", "J", CART_DB_SAVE_TYPE_FLASH_1MBIT, "Pokemon Stadium 2 (Japan)"}, diff --git a/device/cart_db.h b/device/cart_db.h index 11ee2e9..0c0654d 100644 --- a/device/cart_db.h +++ b/device/cart_db.h @@ -16,6 +16,7 @@ enum cart_db_save_type { CART_DB_SAVE_TYPE_EEPROM_16KBIT, CART_DB_SAVE_TYPE_FLASH_1MBIT, CART_DB_SAVE_TYPE_SRAM_256KBIT, + CART_DB_SAVE_TYPE_SRAM_768KBIT, }; struct cart_db_entry { diff --git a/device/options.c b/device/options.c index 6526506..0d63182 100644 --- a/device/options.c +++ b/device/options.c @@ -23,6 +23,7 @@ const struct cen64_options default_cen64_options = { NULL, // eeprom_path 0, // eeprom_size NULL, // sram_path + 0, // sram_size NULL, // flashram_path 0, // is_viewer_present NULL, // controller @@ -122,6 +123,27 @@ int parse_options(struct cen64_options *options, int argc, const char *argv[]) { } options->sram_path = argv[++i]; + options->sram_size = 0x8000; + } + + else if (!strcmp(argv[i], "-sram256k")) { + if ((i + 1) >= (argc - 1)) { + printf("-sram256k requires a path to the save file.\n\n"); + return 1; + } + + options->sram_path = argv[++i]; + options->sram_size = 0x8000; + } + + else if (!strcmp(argv[i], "-sram768k")) { + if ((i + 1) >= (argc - 1)) { + printf("-sram768k requires a path to the save file.\n\n"); + return 1; + } + + options->sram_path = argv[++i]; + options->sram_size = 0x18000; } else if (!strcmp(argv[i], "-flash")) { @@ -279,7 +301,9 @@ void print_command_line_usage(const char *invokation_string) { "Save Options:\n" " -eep4k : Path to 4 kbit EEPROM save.\n" " -eep16k : Path to 16 kbit EEPROM save.\n" - " -sram : Path to SRAM save.\n" + " -sram : Path to 256 kbit SRAM save (alias of -sram256k).\n" + " -sram256k : Path to 256 kbit SRAM save.\n" + " -sram768k : Path to 768 kbit SRAM save.\n" " -flash : Path to FlashRAM save.\n" " For mempak see controller options.\n" diff --git a/device/options.h b/device/options.h index c8d38b9..0854b47 100644 --- a/device/options.h +++ b/device/options.h @@ -22,6 +22,7 @@ struct cen64_options { const char *eeprom_path; size_t eeprom_size; const char *sram_path; + size_t sram_size; const char *flashram_path; int is_viewer_present; diff --git a/pi/controller.c b/pi/controller.c index 0b45e29..9869352 100644 --- a/pi/controller.c +++ b/pi/controller.c @@ -57,14 +57,17 @@ static int pi_dma_read(struct pi_controller *pi) { if (source & 0x7) length -= source & 0x7; - // SRAM and FlashRAM - if (dest >= 0x08000000 && dest < 0x08010000) { - uint32_t addr = dest & 0x00FFFFF; - + // Cartridge Domain 2 Address 2 + if (dest >= 0x08000000 && dest < 0x10000000) { // SRAM - if (pi->sram->ptr != NULL && addr + length <= 0x8000) - memcpy((uint8_t *) (pi->sram->ptr) + addr, pi->bus->ri->ram + source, length); - + if (pi->sram->ptr != NULL) { + // SRAM bank selection bits are [19:18] + uint32_t sram_bank = (dest >> 18) & 3; + // SRAM bank capacity is 256Kbits (0x8000 bytes) + uint32_t sram_offset = (sram_bank * 0x8000) + (dest & 0x7FFF); + if (sram_offset + length <= pi->sram->size) + memcpy((uint8_t *) (pi->sram->ptr) + sram_offset, pi->bus->ri->ram + source, length); + } // FlashRAM: Save the RDRAM destination address. Writing happens // after the system sends the flash write command (handled in // write_flashram) @@ -111,23 +114,28 @@ static int pi_dma_write(struct pi_controller *pi) { else if ((source & 0x05000000) == 0x05000000) dd_dma_write(pi->bus->dd, source, dest, length); - // SRAM and FlashRAM - else if (source >= 0x08000000 && source < 0x08010000) { - uint32_t addr = source & 0x00FFFFF; - - if (pi->sram->ptr != NULL && addr + length <= 0x8000) - memcpy(pi->bus->ri->ram + dest, (const uint8_t *) (pi->sram->ptr) + addr, length); - + // Cartridge Domain 2 Address 2 + else if (source >= 0x08000000 && source < 0x10000000) { + // SRAM + if (pi->sram->ptr != NULL) { + // SRAM bank selection bits are [19:18] + uint32_t sram_bank = (source >> 18) & 3; + // SRAM bank capacity is 256Kbits (0x8000 bytes) + uint32_t sram_offset = (sram_bank * 0x8000) + (source & 0x7FFF); + if (sram_offset + length <= pi->sram->size) + memcpy(pi->bus->ri->ram + dest, (const uint8_t *) (pi->sram->ptr) + sram_offset, length); + } + // FlashRAM else if (pi->flashram.data != NULL) { - // SRAM + uint32_t flashram_offset = source & 0x1FFFF; + // FlashRAM status if (pi->flashram.mode == FLASHRAM_STATUS) { uint64_t status = htonll(pi->flashram.status); memcpy(pi->bus->ri->ram + dest, &status, 8); } - - // FlashRAM + // FlashRAM read else if (pi->flashram.mode == FLASHRAM_READ) - memcpy(pi->bus->ri->ram + dest, pi->flashram.data + addr * 2, length); + memcpy(pi->bus->ri->ram + dest, pi->flashram.data + flashram_offset * 2, length); } }