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); } }