#include #include #include #include #include "../../file_io.h" #include "../../user_io.h" #include "../../spi.h" #include "../../hardware.h" #include "../../menu.h" #include "../../cheats.h" #include "saturn.h" static int need_reset = 0; uint32_t saturn_frame_cnt = 0; uint8_t time_mode; static uint32_t CalcTimerOffset(uint8_t speed) { static uint8_t adj0 = 0x1, adj1 = 0x1, adj2 = 0x1; uint32_t offs; if (speed == 2) { offs = 6 + ((adj2 & 0x03) != 0x00 ? 1 : 0); //6.6 adj2 <<= 1; if (adj2 >= 0x08) adj2 = 0x01; adj0 = adj1 = 0x1; } else if (speed == 1) { offs = 13 + ((adj1 & 0x01) != 0x00 ? 1 : 0); //13.3 adj1 <<= 1; if (adj1 >= 0x08) adj1 = 0x01; adj0 = adj2 = 0x1; } else { offs = 16 + ((adj0 & 0x03) != 0x00 ? 1 : 0); //16.7 adj0 <<= 1; if (adj0 >= 0x08) adj0 = 0x01; adj1 = adj2 = 0x1; } return offs; } void saturn_poll() { static unsigned long poll_timer = 0; static uint8_t last_req = 255; if (!poll_timer || CheckTimer(poll_timer)) { poll_timer = GetTimer(0); uint16_t data_in[6]; uint8_t req = spi_uio_cmd_cont(UIO_CD_GET); if (req != last_req) { last_req = req; for (int i = 0; i < 6; i++) data_in[i] = spi_w(0); DisableIO(); satcdd.SetCommand((uint8_t*)data_in); satcdd.CommandExec(); } else DisableIO(); satcdd.Process(&time_mode); poll_timer += CalcTimerOffset(time_mode); uint16_t* s = (uint16_t*)satcdd.GetStatus(); spi_uio_cmd_cont(UIO_CD_SET); for (int i = 0; i < 6; i++) spi_w(s[i]); DisableIO(); satcdd.Update(); saturn_frame_cnt++; unsigned long curr_timer = GetTimer(0); if (curr_timer >= poll_timer) { poll_timer = curr_timer + CalcTimerOffset(time_mode); #ifdef SATURN_DEBUG user_io_status_set("[63]", 1); printf("\x1b[32mSaturn: "); printf("Time over: next = %lu, curr = %lu", poll_timer, curr_timer); printf("\n\x1b[0m"); #endif // SATURN_DEBUG } #ifdef SATURN_DEBUG else user_io_status_set("[63]", 0); #endif // SATURN_DEBUG } } static char buf[1024]; static void saturn_get_save_without_disk(char *buf) { char *p1, *p2; if ((p1 = strstr(buf, "disc")) != 0 || (p1 = strstr(buf, "Disc")) != 0 || (p1 = strstr(buf, "DISC")) != 0) { p2 = p1 + 4; if (p1 > buf && *(--p1) == '(') p1--; if (p1 > buf && *(--p1) == ' ') p1--; if (*p2 == ' ') p2++; if ((*p2 >= '0' && *p2 <= '9') || (*p2 >= 'a' && *p2 <= 'f') || (*p2 >= 'A' && *p2 <= 'F')) { p2++; if (*p2 == ')') p2++; p1++; strcpy(p1, p2); } } } static void saturn_mount_save(const char *filename) { user_io_set_index(SAVE_IO_INDEX); user_io_set_download(1); if (strlen(filename)) { FileGenerateSavePath(filename, buf); saturn_get_save_without_disk(buf); #ifdef SATURN_DEBUG printf("Saturn save filename = %s\n", buf); #endif // SATURN_DEBUG user_io_file_mount(buf, 0, 1); } else { user_io_file_mount(""); } user_io_set_download(0); } static int saturn_load_rom(const char *basename, const char *name, int sub_index) { strcpy(buf, basename); char *p = strrchr(buf, '/'); if (p) { p++; strcpy(p, name); if (user_io_file_tx(buf, sub_index << 6)) return 1; } return 0; } void saturn_set_image(int num, const char *filename) { static char last_dir[1024] = {}; (void)num; satcdd.Unload(); satcdd.Reset(); int same_game = *filename && *last_dir && !strncmp(last_dir, filename, strlen(last_dir)); strcpy(last_dir, filename); char *p = strrchr(last_dir, '/'); if (p) *p = 0; if (!same_game) { saturn_mount_save(""); user_io_status_set("[0]", 1); saturn_reset(); // load CD BIOS if (!saturn_load_rom(filename, "cd_bios.rom", 0)) // from disk folder. { if (!saturn_load_rom(last_dir, "cd_bios.rom", 0)) // from parent folder. { sprintf(buf, "%s/boot.rom", HomeDir()); // from home folder. if (!user_io_file_tx(buf)) { Info("CD BIOS not found!", 4000); } } } } satcdd.wwf_hack = false; if (strlen(filename)) { if (satcdd.Load(filename) > 0) { satcdd.SendData = saturn_send_data; if (!same_game) { //saturn_load_rom(filename, "cart.rom", 1); saturn_mount_save(filename); //cheats_init(filename, 0); } if (satcdd.GetBootHeader((uint8_t*)buf) > 0) { saturn_send_data((uint8_t*)buf, 256, BOOT_IO_INDEX); char *id = buf + 0x20; if (!strncmp(id,"T-8126H",7) || !strncmp(id, "T-8120G", 7) || !strncmp(id, "T-8112H", 7) || !strncmp(id, "T-99901G", 8) || !strncmp(id, "T-8112G", 7)) satcdd.wwf_hack = true; if (satcdd.wwf_hack) { #ifdef SATURN_DEBUG printf("\x1b[32mSaturn: WWF games hack!!!\n\x1b[0m"); #endif // SATURN_DEBUG } } } } user_io_status_set("[0]", 0); } void saturn_reset() { need_reset = 1; } int saturn_send_data(uint8_t* buf, int len, uint8_t index) { // set index byte user_io_set_index(index); user_io_set_download(1); user_io_file_tx_data(buf, len); user_io_set_download(0); return 1; } static char save_blank[] = { 0x00, 0x42, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6B, 0x00, 0x55, 0x00, 0x70, 0x00, 0x52, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x42, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6B, 0x00, 0x55, 0x00, 0x70, 0x00, 0x52, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x42, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6B, 0x00, 0x55, 0x00, 0x70, 0x00, 0x52, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x42, 0x00, 0x61, 0x00, 0x63, 0x00, 0x6B, 0x00, 0x55, 0x00, 0x70, 0x00, 0x52, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x20, 0x00, 0x46, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x6D, 0x00, 0x61, 0x00, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void saturn_fill_blanksave(uint8_t *buffer, uint32_t lba) { if (lba == 0 || lba == 128) { memcpy(buffer, save_blank, 512); } else { memset(buffer, 0, 512); } }