From 4bb7c3f508414eaf879a31daefaf44534dacedf4 Mon Sep 17 00:00:00 2001 From: Jean-Paul Mari Date: Wed, 11 Oct 2017 20:00:52 -0400 Subject: [PATCH] Create a directory for EEPROMs if it doesn't already exist --- docs/TODO | 150 +++--- docs/vj_ReleaseNotes.txt | 1 + src/eeprom.cpp | 980 +++++++++++++++++++++------------------ src/eeprom.h | 38 +- 4 files changed, 616 insertions(+), 553 deletions(-) rewrite src/eeprom.h (68%) diff --git a/docs/TODO b/docs/TODO index c86f39d..d15efa1 100644 --- a/docs/TODO +++ b/docs/TODO @@ -1,75 +1,75 @@ -Stuff to add/fix for the next release of Virtual Jaguar -------------------------------------------------------- - -- Fix VC behavior to match what a real Jaguar does. Still not sure just what - the heck is going on there. [Shamus] -- Create an EEPROMs directory (or whatever is in EEPROMPath[]) if it doesn't - already exist. [Shamus] -- It would be nice to have the emulator pick up where you last left off, or at - least give you the option of continuing from your last session. This would - require save states, 'natch. ;-) [Shamus] -- It would be nice to have "save states" for instant save/load capability. - [Shamus] -- Cycle accuracy for GPU/DSP/OP/Blitter. [Shamus] -- Need to propagate blitter fixes in the A1 <- A2 direction to the A1 -> A2 - direction and the GPU fixes to various instructions to the DSP. [Shamus] -- Blitter needs fixing. [Shamus] -- In emulator screenshots. [Shamus] -- Audio/video dumping. [Shamus] -- Need to emulate bus contention. [Shamus] -- Need to fix timing in the OP. As it is now, it gives a false impression of - how much it's capable of. [Shamus] -- Fix coming out of fullscreen on Win32. As of now, it doesn't restore the - window position correctly [CJ] -- Fix the Tripper Getem ROM so that it works. It has some tight coupling - between the M68K and the DSP that causes the DSP to starve itself; fixing - this will probably fix a bunch of other timing related issues as well. - [Shamus] - - -Stuff that was added/fixed --------------------------- - -- Controller handling. [Shamus] [DONE--Shamus] -- Full screen option. [Shamus] [DONE--Shamus] -- Command line switches for frontends. [Shamus] [DONE-Shamus] -- Fix DSP code so that it doesn't hang in a spinlock waiting for the sound - buffer to empty. Probably a CS lock contention issue. [Shamus] [DONE-Shamus] -- Need to fix PAL mode to work with the virtual screen code. [DONE--Shamus] -- There are a few ROMs that use some "quasi-illegal" 68K instructions. Need - to patch the 68K core to deal with these in a better way than they are - now. [DONE--Shamus] - NOTE: This behavior was verified on Rayman, the problem was due to attempting - to press both left & right at the same time! -- We need a comprehensive way of determining what gets written where and - by whom (i.e., blitter wrote to range $F03000-$F03230) in order to figure - out the remaining problems with various ROMs. [DONE--Shamus] -- Would also be nice to be able to dynamically change the keybindings for - the various keys on the emulated Jaguar controller while inside the emulator. - [DONE--Shamus] -- Make sure that VJ doesn't crash if the useJaguarBIOS key is set to 1 and the - BIOS file isn't available. [DONE--Shamus] -- There is a bug either with the GPU or the blitter (most likely the latter) - which causes the spinning "A"s in the BIOS startup code to be corrupted - when they are showing their backsides. [Shamus] [DONE--Shamus] - NOTE: This behavior has been verified on a real Jaguar and as such is not - an emulator bug. A Jaguar boot ROM bug, yes, but not ours. ;-) -- Make it possible to completely disable the GUI (using a switch like -nogui - or the like) for people running VJ in a cabinet. [Shamus] [DONE--Shamus] -- Code to stretch the display in a generic way would be nice. [Shamus] - [DONE for OpenGL--nwagenaar] -- Would be nice to have a GUI for things that are set on the command line or - in the config file. [Shamus] [DONE--Shamus] -- DSP code needs to be rewritten. [Shamus] [DONE but still work to be done--Shamus] -- We need to have an external configuration file for remembering a user's - preferences, such as key bindings, etc. [Shamus] [DONE--Shamus] -- We need to come up with a way to fix the aspect ratio for pixel modes that - aren't square (PWIDTH != 4). [Shamus] [DONE for OpenGL--Shamus] -- GUI for ROM selection [Shamus] [DONE--Shamus] -- Need to rewrite the main Jaguar execution loop to increment the VC by one - instead of by two, which is how the real Jaguar works. [Shamus] [DONE--Shamus] -- Sound needs a rewrite. With SDL, this shouldn't be much of a problem. - Of course, whoever does this should realize that the PCM outs are probably - not being used for a majority of the ROMs out there--according to the JTRM, - you're supposed to use the I2S interface to output sound since the PCM outs - aren't even physically hooked up in the console! [Shamus] [DONE--Shamus] +Stuff to add/fix for the next release of Virtual Jaguar +------------------------------------------------------- + +- Fix VC behavior to match what a real Jaguar does. Still not sure just what + the heck is going on there. [Shamus] +- It would be nice to have the emulator pick up where you last left off, or at + least give you the option of continuing from your last session. This would + require save states, 'natch. ;-) [Shamus] +- It would be nice to have "save states" for instant save/load capability. + [Shamus] +- Cycle accuracy for GPU/DSP/OP/Blitter. [Shamus] +- Need to propagate blitter fixes in the A1 <- A2 direction to the A1 -> A2 + direction and the GPU fixes to various instructions to the DSP. [Shamus] +- Blitter needs fixing. [Shamus] +- In emulator screenshots. [Shamus] +- Audio/video dumping. [Shamus] +- Need to emulate bus contention. [Shamus] +- Need to fix timing in the OP. As it is now, it gives a false impression of + how much it's capable of. [Shamus] +- Fix coming out of fullscreen on Win32. As of now, it doesn't restore the + window position correctly [CJ] +- Fix the Tripper Getem ROM so that it works. It has some tight coupling + between the M68K and the DSP that causes the DSP to starve itself; fixing + this will probably fix a bunch of other timing related issues as well. + [Shamus] + + +Stuff that was added/fixed +-------------------------- + +- Create an EEPROMs directory (or whatever is in EEPROMPath[]) if it doesn't + already exist. [Shamus] [DONE--Flynn] +- Controller handling. [Shamus] [DONE--Shamus] +- Full screen option. [Shamus] [DONE--Shamus] +- Command line switches for frontends. [Shamus] [DONE-Shamus] +- Fix DSP code so that it doesn't hang in a spinlock waiting for the sound + buffer to empty. Probably a CS lock contention issue. [Shamus] [DONE-Shamus] +- Need to fix PAL mode to work with the virtual screen code. [DONE--Shamus] +- There are a few ROMs that use some "quasi-illegal" 68K instructions. Need + to patch the 68K core to deal with these in a better way than they are + now. [DONE--Shamus] + NOTE: This behavior was verified on Rayman, the problem was due to attempting + to press both left & right at the same time! +- We need a comprehensive way of determining what gets written where and + by whom (i.e., blitter wrote to range $F03000-$F03230) in order to figure + out the remaining problems with various ROMs. [DONE--Shamus] +- Would also be nice to be able to dynamically change the keybindings for + the various keys on the emulated Jaguar controller while inside the emulator. + [DONE--Shamus] +- Make sure that VJ doesn't crash if the useJaguarBIOS key is set to 1 and the + BIOS file isn't available. [DONE--Shamus] +- There is a bug either with the GPU or the blitter (most likely the latter) + which causes the spinning "A"s in the BIOS startup code to be corrupted + when they are showing their backsides. [Shamus] [DONE--Shamus] + NOTE: This behavior has been verified on a real Jaguar and as such is not + an emulator bug. A Jaguar boot ROM bug, yes, but not ours. ;-) +- Make it possible to completely disable the GUI (using a switch like -nogui + or the like) for people running VJ in a cabinet. [Shamus] [DONE--Shamus] +- Code to stretch the display in a generic way would be nice. [Shamus] + [DONE for OpenGL--nwagenaar] +- Would be nice to have a GUI for things that are set on the command line or + in the config file. [Shamus] [DONE--Shamus] +- DSP code needs to be rewritten. [Shamus] [DONE but still work to be done--Shamus] +- We need to have an external configuration file for remembering a user's + preferences, such as key bindings, etc. [Shamus] [DONE--Shamus] +- We need to come up with a way to fix the aspect ratio for pixel modes that + aren't square (PWIDTH != 4). [Shamus] [DONE for OpenGL--Shamus] +- GUI for ROM selection [Shamus] [DONE--Shamus] +- Need to rewrite the main Jaguar execution loop to increment the VC by one + instead of by two, which is how the real Jaguar works. [Shamus] [DONE--Shamus] +- Sound needs a rewrite. With SDL, this shouldn't be much of a problem. + Of course, whoever does this should realize that the PCM outs are probably + not being used for a majority of the ROMs out there--according to the JTRM, + you're supposed to use the I2S interface to output sound since the PCM outs + aren't even physically hooked up in the console! [Shamus] [DONE--Shamus] diff --git a/docs/vj_ReleaseNotes.txt b/docs/vj_ReleaseNotes.txt index 73f84e8..361dd1b 100644 --- a/docs/vj_ReleaseNotes.txt +++ b/docs/vj_ReleaseNotes.txt @@ -15,6 +15,7 @@ Release 3 (WiP) 10) Solved an interference between the HW labels setting and the one used by the debugger -- The setting is now only the reference used 11) Fixed the SP (Stack) window UI potential missing data +12) Create a directory for EEPROMs (based on the EEPROMs setting) if it doesn't already exist Release 2 (3rd September 2017) ------------------------------ diff --git a/src/eeprom.cpp b/src/eeprom.cpp index 66c4a4c..9062c2c 100644 --- a/src/eeprom.cpp +++ b/src/eeprom.cpp @@ -1,459 +1,521 @@ -// -// Jaguar EEPROM handler -// -// by Cal2 -// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) -// Cleanups/enhancements by James Hammons -// (C) 2010 Underground Software -// -// JLH = James Hammons -// -// Who When What -// --- ---------- ------------------------------------------------------------ -// JLH 01/16/2010 Created this log ;-) -// - -#include "eeprom.h" - -#include -#include // For memset -#include "jaguar.h" -#include "log.h" -#include "settings.h" - -//#define eeprom_LOG - -static uint16_t eeprom_ram[64]; -static uint16_t cdromEEPROM[64]; - -// -// Private function prototypes -// - -static void EEPROMSave(void); -static void eeprom_set_di(uint32_t state); -static void eeprom_set_cs(uint32_t state); -static uint32_t eeprom_get_do(void); -void ReadEEPROMFromFile(FILE * file, uint16_t * ram); -void WriteEEPROMToFile(FILE * file, uint16_t * ram); - - -enum { EE_STATE_START = 1, EE_STATE_OP_A, EE_STATE_OP_B, EE_STATE_0, EE_STATE_1, - EE_STATE_2, EE_STATE_3, EE_STATE_0_0, EE_READ_ADDRESS, EE_STATE_0_0_0, - EE_STATE_0_0_1, EE_STATE_0_0_2, EE_STATE_0_0_3, EE_STATE_0_0_1_0, EE_READ_DATA, - EE_STATE_BUSY, EE_STATE_1_0, EE_STATE_1_1, EE_STATE_2_0, EE_STATE_3_0 }; - -// Local global variables - -static uint16_t jerry_ee_state = EE_STATE_START; -static uint16_t jerry_ee_op = 0; -static uint16_t jerry_ee_rstate = 0; -static uint16_t jerry_ee_address_data = 0; -static uint16_t jerry_ee_address_cnt = 6; -static uint16_t jerry_ee_data = 0; -static uint16_t jerry_ee_data_cnt = 16; -static uint16_t jerry_writes_enabled = 0; -static uint16_t jerry_ee_direct_jump = 0; - -static char eeprom_filename[MAX_PATH]; -static char cdromEEPROMFilename[MAX_PATH]; -static bool haveEEPROM = false; -static bool haveCDROMEEPROM = false; - - -void EepromInit(void) -{ - // No need for EEPROM for the Memory Track device :-P - if (jaguarMainROMCRC32 == 0xFDF37F47) - { - WriteLog("EEPROM: Memory Track device detected...\n"); - return; - } - - // Handle regular cartridge EEPROM - sprintf(eeprom_filename, "%s%08X.eeprom", vjs.EEPROMPath, (unsigned int)jaguarMainROMCRC32); - sprintf(cdromEEPROMFilename, "%scdrom.eeprom", vjs.EEPROMPath); - FILE * fp = fopen(eeprom_filename, "rb"); - - if (fp) - { - ReadEEPROMFromFile(fp, eeprom_ram); - fclose(fp); - WriteLog("EEPROM: Loaded from %s\n", eeprom_filename); - haveEEPROM = true; - } - else - WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename); - - // Handle JagCD EEPROM - fp = fopen(cdromEEPROMFilename, "rb"); - - if (fp) - { - ReadEEPROMFromFile(fp, cdromEEPROM); - fclose(fp); - WriteLog("EEPROM: Loaded from cdrom.eeprom\n"); - haveCDROMEEPROM = true; - } - else - WriteLog("EEPROM: Could not open file \"%s\"!\n", cdromEEPROMFilename); -} - - -void EepromReset(void) -{ - if (!haveEEPROM) - memset(eeprom_ram, 0xFF, 64 * sizeof(uint16_t)); - - if (!haveCDROMEEPROM) - memset(cdromEEPROM, 0xFF, 64 * sizeof(uint16_t)); -} - - -void EepromDone(void) -{ - WriteLog("EEPROM: Done.\n"); -} - - -static void EEPROMSave(void) -{ - // Write out regular cartridge EEPROM data - FILE * fp = fopen(eeprom_filename, "wb"); - - if (fp) - { - WriteEEPROMToFile(fp, eeprom_ram); - fclose(fp); - } - else - WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename); - - // Write out JagCD EEPROM data - fp = fopen(cdromEEPROMFilename, "wb"); - - if (fp) - { - WriteEEPROMToFile(fp, cdromEEPROM); - fclose(fp); - } - else - WriteLog("EEPROM: Could not create file \"%s!\"\n", cdromEEPROMFilename); -} - - -// -// Read/write EEPROM files to disk in an endian safe manner -// -void ReadEEPROMFromFile(FILE * file, uint16_t * ram) -{ - uint8_t buffer[128]; - size_t ignored = fread(buffer, 1, 128, file); - - for(int i=0; i<64; i++) - ram[i] = (buffer[(i * 2) + 0] << 8) | buffer[(i * 2) + 1]; -} - - -void WriteEEPROMToFile(FILE * file, uint16_t * ram) -{ - uint8_t buffer[128]; - - for(int i=0; i<64; i++) - { - buffer[(i * 2) + 0] = ram[i] >> 8; - buffer[(i * 2) + 1] = ram[i] & 0xFF; - } - - fwrite(buffer, 1, 128, file); -} - - -uint8_t EepromReadByte(uint32_t offset) -{ - switch (offset) - { - case 0xF14001: - return eeprom_get_do(); - case 0xF14801: - break; - case 0xF15001: - eeprom_set_cs(1); - break; -// default: WriteLog("EEPROM: unmapped 0x%.8x\n", offset); break; - } - - return 0x00; -} - - -uint16_t EepromReadWord(uint32_t offset) -{ - return ((uint16_t)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1); -} - - -void EepromWriteByte(uint32_t offset, uint8_t data) -{ - switch (offset) - { - case 0xF14001: - break; - case 0xF14801: - eeprom_set_di(data & 0x01); - break; - case 0xF15001: - eeprom_set_cs(1); - break; -// default: WriteLog("eeprom: unmapped 0x%.8x\n",offset); break; - } -} - - -void EepromWriteWord(uint32_t offset, uint16_t data) -{ - EepromWriteByte(offset + 0, (data >> 8) & 0xFF); - EepromWriteByte(offset + 1, data & 0xFF); -} - - -/* -; -; Commands specific to the National Semiconductor NM93C14 -; -; -; 9-bit commands.. -; 876543210 -eEWDS equ %100000000 ;Erase/Write disable (default) -eWRAL equ %100010000 ;Writes all registers -eERAL equ %100100000 ;Erase all registers -eEWEN equ %100110000 ;Erase/write Enable -eWRITE equ %101000000 ;Write selected register -eREAD equ %110000000 ;read from EEPROM -eERASE equ %111000000 ;Erase selected register -*/ - - -static void eeprom_set_di(uint32_t data) -{ -// WriteLog("eeprom: di=%i\n",data); -// WriteLog("eeprom: state %i\n",jerry_ee_state); - switch (jerry_ee_state) - { - case EE_STATE_START: - jerry_ee_state = EE_STATE_OP_A; - break; - case EE_STATE_OP_A: - jerry_ee_op = (data << 1); - jerry_ee_state = EE_STATE_OP_B; - break; - case EE_STATE_OP_B: - jerry_ee_op |= data; - jerry_ee_direct_jump = 0; -// WriteLog("eeprom: opcode %i\n",jerry_ee_op); - - switch (jerry_ee_op) - { - // Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS - case 0: jerry_ee_state = EE_STATE_0; break; - // Opcode 01: eWRITE (Write selected register) - case 1: jerry_ee_state = EE_STATE_1; break; - // Opcode 10: eREAD (Read from EEPROM) - case 2: jerry_ee_state = EE_STATE_2; break; - // Opcode 11: eERASE (Erase selected register) - case 3: jerry_ee_state = EE_STATE_3; break; - } - - eeprom_set_di(data); - break; - case EE_STATE_0: - jerry_ee_rstate = EE_STATE_0_0; - jerry_ee_state = EE_READ_ADDRESS; - jerry_ee_direct_jump = 1; - jerry_ee_address_cnt = 6; - jerry_ee_address_data = 0; - break; - case EE_STATE_0_0: - switch ((jerry_ee_address_data >> 4) & 0x03) - { - // Opcode 00 00: eEWDS (Erase/Write disable) - case 0: jerry_ee_state=EE_STATE_0_0_0; break; - // Opcode 00 01: eWRAL (Write all registers) - case 1: jerry_ee_state=EE_STATE_0_0_1; break; - // Opcode 00 10: eERAL (Erase all registers) - case 2: jerry_ee_state=EE_STATE_0_0_2; break; - // Opcode 00 11: eEWEN (Erase/Write enable) - case 3: jerry_ee_state=EE_STATE_0_0_3; break; - } - - eeprom_set_di(data); - break; - case EE_STATE_0_0_0: - // writes disable - // WriteLog("eeprom: read only\n"); - jerry_writes_enabled = 0; - jerry_ee_state = EE_STATE_START; - break; - case EE_STATE_0_0_1: - // writes all - jerry_ee_rstate = EE_STATE_0_0_1_0; - jerry_ee_state = EE_READ_DATA; - jerry_ee_data_cnt = 16; - jerry_ee_data = 0; - jerry_ee_direct_jump = 1; - break; - case EE_STATE_0_0_1_0: - // WriteLog("eeprom: filling eeprom with 0x%.4x\n",data); - if (jerry_writes_enabled) - { - for(int i=0; i<64; i++) - eeprom_ram[i] = jerry_ee_data; - - EEPROMSave(); // Save it NOW! - } - - //else - // WriteLog("eeprom: not writing because read only\n"); - jerry_ee_state = EE_STATE_BUSY; - break; - case EE_STATE_0_0_2: - // erase all - //WriteLog("eeprom: erasing eeprom\n"); - if (jerry_writes_enabled) - for(int i=0; i<64; i++) - eeprom_ram[i] = 0xFFFF; - - jerry_ee_state = EE_STATE_BUSY; - break; - case EE_STATE_0_0_3: - // writes enable - //WriteLog("eeprom: read/write\n"); - jerry_writes_enabled = 1; - jerry_ee_state = EE_STATE_START; - break; - case EE_STATE_1: - jerry_ee_rstate = EE_STATE_1_0; - jerry_ee_state = EE_READ_ADDRESS; - jerry_ee_address_cnt = 6; - jerry_ee_address_data = 0; - jerry_ee_direct_jump = 1; - break; - case EE_STATE_1_0: - jerry_ee_rstate = EE_STATE_1_1; - jerry_ee_state = EE_READ_DATA; - jerry_ee_data_cnt = 16; - jerry_ee_data = 0; - jerry_ee_direct_jump = 1; - break; - case EE_STATE_1_1: - //WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data); - if (jerry_writes_enabled) - { - eeprom_ram[jerry_ee_address_data] = jerry_ee_data; - EEPROMSave(); // Save it NOW! - } - - jerry_ee_state = EE_STATE_BUSY; - break; - case EE_STATE_2: - jerry_ee_rstate = EE_STATE_2_0; - jerry_ee_state = EE_READ_ADDRESS; - jerry_ee_address_cnt = 6; - jerry_ee_address_data = 0; - jerry_ee_data_cnt = 16; - jerry_ee_data = 0; - break; - case EE_STATE_3: - jerry_ee_rstate = EE_STATE_3_0; - jerry_ee_state = EE_READ_ADDRESS; - jerry_ee_address_cnt = 6; - jerry_ee_address_data = 0; - jerry_ee_direct_jump = 1; - break; - case EE_STATE_3_0: - //WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data); - if (jerry_writes_enabled) - eeprom_ram[jerry_ee_address_data] = 0xFFFF; - - jerry_ee_state = EE_STATE_BUSY; - break; - case EE_READ_DATA: - //WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1); - jerry_ee_data <<= 1; - jerry_ee_data |= data; - jerry_ee_data_cnt--; - - if (!jerry_ee_data_cnt) - { - jerry_ee_state = jerry_ee_rstate; - - if (jerry_ee_direct_jump) - eeprom_set_di(data); - } - - break; - case EE_READ_ADDRESS: - jerry_ee_address_data <<= 1; - jerry_ee_address_data |= data; - jerry_ee_address_cnt--; -// WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt); - - if (!jerry_ee_address_cnt) - { - jerry_ee_state = jerry_ee_rstate; - //WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data); - - if (jerry_ee_direct_jump) - eeprom_set_di(data); - } - - break; - default: - jerry_ee_state = EE_STATE_OP_A; - } -} - - -static void eeprom_set_cs(uint32_t /*state*/) -{ -// WriteLog("eeprom: cs=%i\n",state); - jerry_ee_state = EE_STATE_START; - jerry_ee_op = 0; - jerry_ee_rstate = 0; - jerry_ee_address_data = 0; - jerry_ee_address_cnt = 6; - jerry_ee_data = 0; - jerry_ee_data_cnt = 16; - jerry_writes_enabled = 1; -} - - -static uint32_t eeprom_get_do(void) -{ - uint16_t data = 1; - - switch (jerry_ee_state) - { - case EE_STATE_START: - data = 1; - break; - case EE_STATE_BUSY: - jerry_ee_state = EE_STATE_START; - data = 0; - break; - case EE_STATE_2_0: - jerry_ee_data_cnt--; - data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01; - - if (!jerry_ee_data_cnt) - { - //WriteLog("eeprom: read 0x%.4x at 0x%.2x cpu %i pc=0x%.8x\n",eeprom_ram[jerry_ee_address_data],jerry_ee_address_data,jaguar_cpu_in_exec,s68000readPC()); - jerry_ee_state = EE_STATE_START; - } - break; - } - -// WriteLog("eeprom: do=%i\n",data); - return data; -} - +// +// Jaguar EEPROM handler +// +// by Cal2 +// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS) +// Cleanups/enhancements by James Hammons +// (C) 2010 Underground Software +// +// JLH = James Hammons +// JPM = Jean-Paul Mari +// +// Who When What +// --- ---------- ------------------------------------------------------------ +// JLH 01/16/2010 Created this log ;-) +// JPM 10/11/2017 Directory detection and creation if missing +// + +#include "eeprom.h" +#include +#include +#include // For memset +#include "jaguar.h" +#include "log.h" +#include "settings.h" + +#define eeprom_LOG + +static uint16_t eeprom_ram[64]; +static uint16_t cdromEEPROM[64]; + +// +// Private function prototypes +// + +static void EEPROMSave(void); +static void eeprom_set_di(uint32_t state); +static void eeprom_set_cs(uint32_t state); +static uint32_t eeprom_get_do(void); +void ReadEEPROMFromFile(FILE * file, uint16_t * ram); +void WriteEEPROMToFile(FILE * file, uint16_t * ram); + + +enum { EE_STATE_START = 1, EE_STATE_OP_A, EE_STATE_OP_B, EE_STATE_0, EE_STATE_1, + EE_STATE_2, EE_STATE_3, EE_STATE_0_0, EE_READ_ADDRESS, EE_STATE_0_0_0, + EE_STATE_0_0_1, EE_STATE_0_0_2, EE_STATE_0_0_3, EE_STATE_0_0_1_0, EE_READ_DATA, + EE_STATE_BUSY, EE_STATE_1_0, EE_STATE_1_1, EE_STATE_2_0, EE_STATE_3_0 }; + +// Local global variables + +static uint16_t jerry_ee_state = EE_STATE_START; +static uint16_t jerry_ee_op = 0; +static uint16_t jerry_ee_rstate = 0; +static uint16_t jerry_ee_address_data = 0; +static uint16_t jerry_ee_address_cnt = 6; +static uint16_t jerry_ee_data = 0; +static uint16_t jerry_ee_data_cnt = 16; +static uint16_t jerry_writes_enabled = 0; +static uint16_t jerry_ee_direct_jump = 0; + +static char eeprom_filename[MAX_PATH]; +static char cdromEEPROMFilename[MAX_PATH]; +static bool haveEEPROM = false; +static bool haveCDROMEEPROM = false; + + +// EEPROM initialisations +void EepromInit(void) +{ + FILE * fp; + + // No need for EEPROM for the Memory Track device :-P + if (jaguarMainROMCRC32 == 0xFDF37F47) + { + WriteLog("EEPROM: Memory Track device detected...\n"); + } + else + { + // Handle regular cartridge EEPROM + sprintf(eeprom_filename, "%s%08X.eeprom", vjs.EEPROMPath, (unsigned int)jaguarMainROMCRC32); + fp = fopen(eeprom_filename, "rb"); + + if (fp) + { + ReadEEPROMFromFile(fp, eeprom_ram); + fclose(fp); + WriteLog("EEPROM: Loaded from %s\n", eeprom_filename); + haveEEPROM = true; + } + else + { + WriteLog("EEPROM: Could not open file \"%s\"!\n", eeprom_filename); + } + + // Handle JagCD EEPROM + sprintf(cdromEEPROMFilename, "%scdrom.eeprom", vjs.EEPROMPath); + fp = fopen(cdromEEPROMFilename, "rb"); + + if (fp) + { + ReadEEPROMFromFile(fp, cdromEEPROM); + fclose(fp); + WriteLog("EEPROM: Loaded from cdrom.eeprom\n"); + haveCDROMEEPROM = true; + } + else + { + WriteLog("EEPROM: Could not open file \"%s\"!\n", cdromEEPROMFilename); + } + } +} + + +// EEPROM reset +void EepromReset(void) +{ + if (!haveEEPROM) + memset(eeprom_ram, 0xFF, 64 * sizeof(uint16_t)); + + if (!haveCDROMEEPROM) + memset(cdromEEPROM, 0xFF, 64 * sizeof(uint16_t)); +} + + +// +void EepromDone(void) +{ + WriteLog("EEPROM: Done.\n"); +} + + +// EEPROM save +static void EEPROMSave(void) +{ + FILE * fp; + + // Check if EEPROM directory exists and try to create it if not + if (_mkdir(vjs.EEPROMPath)) + { + WriteLog("EEPROM: Could not create directory \"%s!\"\n", vjs.EEPROMPath); + } + + // Write out regular cartridge EEPROM data + fp = fopen(eeprom_filename, "wb"); + if (fp) + { + WriteEEPROMToFile(fp, eeprom_ram); + fclose(fp); + } + else + { + WriteLog("EEPROM: Could not create file \"%s!\"\n", eeprom_filename); + } + + // Write out JagCD EEPROM data + fp = fopen(cdromEEPROMFilename, "wb"); + if (fp) + { + WriteEEPROMToFile(fp, cdromEEPROM); + fclose(fp); + } + else + { + WriteLog("EEPROM: Could not create file \"%s!\"\n", cdromEEPROMFilename); + } +} + + +// +// Read/write EEPROM files to disk in an endian safe manner +// +void ReadEEPROMFromFile(FILE * file, uint16_t * ram) +{ + uint8_t buffer[128]; + size_t ignored = fread(buffer, 1, 128, file); + + for(int i=0; i<64; i++) + ram[i] = (buffer[(i * 2) + 0] << 8) | buffer[(i * 2) + 1]; +} + + +void WriteEEPROMToFile(FILE * file, uint16_t * ram) +{ + uint8_t buffer[128]; + + for(int i=0; i<64; i++) + { + buffer[(i * 2) + 0] = ram[i] >> 8; + buffer[(i * 2) + 1] = ram[i] & 0xFF; + } + + fwrite(buffer, 1, 128, file); +} + + +uint8_t EepromReadByte(uint32_t offset) +{ + switch (offset) + { + case 0xF14001: + return eeprom_get_do(); + case 0xF14801: + break; + case 0xF15001: + eeprom_set_cs(1); + break; + default: +#ifdef eeprom_LOG + WriteLog("EEPROM: unmapped 0x%.8x\n", offset); +#endif + break; + } + + return 0x00; +} + + +uint16_t EepromReadWord(uint32_t offset) +{ + return ((uint16_t)EepromReadByte(offset + 0) << 8) | EepromReadByte(offset + 1); +} + + +void EepromWriteByte(uint32_t offset, uint8_t data) +{ + switch (offset) + { + case 0xF14001: + break; + case 0xF14801: + eeprom_set_di(data & 0x01); + break; + case 0xF15001: + eeprom_set_cs(1); + break; + default: +#ifdef eeprom_LOG + WriteLog("eeprom: unmapped 0x%.8x\n",offset); +#endif + break; + } +} + + +void EepromWriteWord(uint32_t offset, uint16_t data) +{ + EepromWriteByte(offset + 0, (data >> 8) & 0xFF); + EepromWriteByte(offset + 1, data & 0xFF); +} + + +/* +; +; Commands specific to the National Semiconductor NM93C14 +; +; +; 9-bit commands.. +; 876543210 +eEWDS equ %100000000 ;Erase/Write disable (default) +eWRAL equ %100010000 ;Writes all registers +eERAL equ %100100000 ;Erase all registers +eEWEN equ %100110000 ;Erase/write Enable +eWRITE equ %101000000 ;Write selected register +eREAD equ %110000000 ;read from EEPROM +eERASE equ %111000000 ;Erase selected register +*/ + + +static void eeprom_set_di(uint32_t data) +{ +#ifdef eeprom_LOG + WriteLog("eeprom: di=%i\n",data); + WriteLog("eeprom: state %i\n",jerry_ee_state); +#endif + + switch (jerry_ee_state) + { + case EE_STATE_START: + jerry_ee_state = EE_STATE_OP_A; + break; + case EE_STATE_OP_A: + jerry_ee_op = (data << 1); + jerry_ee_state = EE_STATE_OP_B; + break; + case EE_STATE_OP_B: + jerry_ee_op |= data; + jerry_ee_direct_jump = 0; +#ifdef eeprom_LOG + WriteLog("eeprom: opcode %i\n",jerry_ee_op); +#endif + + switch (jerry_ee_op) + { + // Opcode 00: eEWEN, eERAL, eWRAL, eEWNDS + case 0: jerry_ee_state = EE_STATE_0; break; + // Opcode 01: eWRITE (Write selected register) + case 1: jerry_ee_state = EE_STATE_1; break; + // Opcode 10: eREAD (Read from EEPROM) + case 2: jerry_ee_state = EE_STATE_2; break; + // Opcode 11: eERASE (Erase selected register) + case 3: jerry_ee_state = EE_STATE_3; break; + } + + eeprom_set_di(data); + break; + case EE_STATE_0: + jerry_ee_rstate = EE_STATE_0_0; + jerry_ee_state = EE_READ_ADDRESS; + jerry_ee_direct_jump = 1; + jerry_ee_address_cnt = 6; + jerry_ee_address_data = 0; + break; + case EE_STATE_0_0: + switch ((jerry_ee_address_data >> 4) & 0x03) + { + // Opcode 00 00: eEWDS (Erase/Write disable) + case 0: jerry_ee_state=EE_STATE_0_0_0; break; + // Opcode 00 01: eWRAL (Write all registers) + case 1: jerry_ee_state=EE_STATE_0_0_1; break; + // Opcode 00 10: eERAL (Erase all registers) + case 2: jerry_ee_state=EE_STATE_0_0_2; break; + // Opcode 00 11: eEWEN (Erase/Write enable) + case 3: jerry_ee_state=EE_STATE_0_0_3; break; + } + + eeprom_set_di(data); + break; + case EE_STATE_0_0_0: + // writes disable +#ifdef eeprom_LOG + WriteLog("eeprom: read only\n"); +#endif + jerry_writes_enabled = 0; + jerry_ee_state = EE_STATE_START; + break; + case EE_STATE_0_0_1: + // writes all + jerry_ee_rstate = EE_STATE_0_0_1_0; + jerry_ee_state = EE_READ_DATA; + jerry_ee_data_cnt = 16; + jerry_ee_data = 0; + jerry_ee_direct_jump = 1; + break; + case EE_STATE_0_0_1_0: +#ifdef eeprom_LOG + WriteLog("eeprom: filling eeprom with 0x%.4x\n",data); +#endif + if (jerry_writes_enabled) + { + for(int i=0; i<64; i++) + eeprom_ram[i] = jerry_ee_data; + + EEPROMSave(); // Save it NOW! + } + + //else +#ifdef eeprom_LOG + WriteLog("eeprom: not writing because read only\n"); +#endif + jerry_ee_state = EE_STATE_BUSY; + break; + case EE_STATE_0_0_2: + // erase all +#ifdef eeprom_LOG + WriteLog("eeprom: erasing eeprom\n"); +#endif + if (jerry_writes_enabled) + for(int i=0; i<64; i++) + eeprom_ram[i] = 0xFFFF; + + jerry_ee_state = EE_STATE_BUSY; + break; + case EE_STATE_0_0_3: + // writes enable +#ifdef eeprom_LOG + WriteLog("eeprom: read/write\n"); +#endif + jerry_writes_enabled = 1; + jerry_ee_state = EE_STATE_START; + break; + case EE_STATE_1: + jerry_ee_rstate = EE_STATE_1_0; + jerry_ee_state = EE_READ_ADDRESS; + jerry_ee_address_cnt = 6; + jerry_ee_address_data = 0; + jerry_ee_direct_jump = 1; + break; + case EE_STATE_1_0: + jerry_ee_rstate = EE_STATE_1_1; + jerry_ee_state = EE_READ_DATA; + jerry_ee_data_cnt = 16; + jerry_ee_data = 0; + jerry_ee_direct_jump = 1; + break; + case EE_STATE_1_1: +#ifdef eeprom_LOG + WriteLog("eeprom: writing 0x%.4x at 0x%.2x\n",jerry_ee_data,jerry_ee_address_data); +#endif + if (jerry_writes_enabled) + { + eeprom_ram[jerry_ee_address_data] = jerry_ee_data; + EEPROMSave(); // Save it NOW! + } + + jerry_ee_state = EE_STATE_BUSY; + break; + case EE_STATE_2: + jerry_ee_rstate = EE_STATE_2_0; + jerry_ee_state = EE_READ_ADDRESS; + jerry_ee_address_cnt = 6; + jerry_ee_address_data = 0; + jerry_ee_data_cnt = 16; + jerry_ee_data = 0; + break; + case EE_STATE_3: + jerry_ee_rstate = EE_STATE_3_0; + jerry_ee_state = EE_READ_ADDRESS; + jerry_ee_address_cnt = 6; + jerry_ee_address_data = 0; + jerry_ee_direct_jump = 1; + break; + case EE_STATE_3_0: +#ifdef eeprom_LOG + WriteLog("eeprom: erasing 0x%.2x\n",jerry_ee_address_data); +#endif + if (jerry_writes_enabled) + eeprom_ram[jerry_ee_address_data] = 0xFFFF; + + jerry_ee_state = EE_STATE_BUSY; + break; + case EE_READ_DATA: +#ifdef eeprom_LOG + WriteLog("eeprom:\t\t\t%i bit %i\n",data,jerry_ee_data_cnt-1); +#endif + jerry_ee_data <<= 1; + jerry_ee_data |= data; + jerry_ee_data_cnt--; + + if (!jerry_ee_data_cnt) + { + jerry_ee_state = jerry_ee_rstate; + + if (jerry_ee_direct_jump) + eeprom_set_di(data); + } + + break; + case EE_READ_ADDRESS: + jerry_ee_address_data <<= 1; + jerry_ee_address_data |= data; + jerry_ee_address_cnt--; +#ifdef eeprom_LOG + WriteLog("eeprom:\t%i bits remaining\n",jerry_ee_address_cnt); +#endif + + if (!jerry_ee_address_cnt) + { + jerry_ee_state = jerry_ee_rstate; +#ifdef eeprom_LOG + WriteLog("eeprom:\t\tread address 0x%.2x\n",jerry_ee_address_data); +#endif + + if (jerry_ee_direct_jump) + eeprom_set_di(data); + } + + break; + default: + jerry_ee_state = EE_STATE_OP_A; + } +} + + +static void eeprom_set_cs(uint32_t state) +{ +#ifdef eeprom_LOG + WriteLog("eeprom: cs=%i\n",state); +#endif + jerry_ee_state = EE_STATE_START; + jerry_ee_op = 0; + jerry_ee_rstate = 0; + jerry_ee_address_data = 0; + jerry_ee_address_cnt = 6; + jerry_ee_data = 0; + jerry_ee_data_cnt = 16; + jerry_writes_enabled = 1; +} + + +static uint32_t eeprom_get_do(void) +{ + uint16_t data = 1; + + switch (jerry_ee_state) + { + case EE_STATE_START: + data = 1; + break; + case EE_STATE_BUSY: + jerry_ee_state = EE_STATE_START; + data = 0; + break; + case EE_STATE_2_0: + jerry_ee_data_cnt--; + data = (eeprom_ram[jerry_ee_address_data] >> jerry_ee_data_cnt) & 0x01; + + if (!jerry_ee_data_cnt) + { +#ifdef eeprom_LOG + //WriteLog("eeprom: read 0x%.4x at 0x%.2x cpu %i pc=0x%.8x\n",eeprom_ram[jerry_ee_address_data],jerry_ee_address_data,jaguar_cpu_in_exec,s68000readPC()); +#endif + jerry_ee_state = EE_STATE_START; + } + break; + } + +#ifdef eeprom_LOG + WriteLog("eeprom: do=%i\n",data); +#endif + return data; +} + diff --git a/src/eeprom.h b/src/eeprom.h dissimilarity index 68% index 0f89ade..b98c189 100644 --- a/src/eeprom.h +++ b/src/eeprom.h @@ -1,19 +1,19 @@ -// -// EEPROM.H: Header file -// - -#ifndef __EEPROM_H__ -#define __EEPROM_H__ - -#include - -void EepromInit(void); -void EepromReset(void); -void EepromDone(void); - -uint8_t EepromReadByte(uint32_t offset); -uint16_t EepromReadWord(uint32_t offset); -void EepromWriteByte(uint32_t offset, uint8_t data); -void EepromWriteWord(uint32_t offset, uint16_t data); - -#endif // __EEPROM_H__ +// +// EEPROM.H: Header file +// + +#ifndef __EEPROM_H__ +#define __EEPROM_H__ + +#include + +extern void EepromInit(void); +extern void EepromReset(void); +extern void EepromDone(void); + +extern uint8_t EepromReadByte(uint32_t offset); +extern uint16_t EepromReadWord(uint32_t offset); +extern void EepromWriteByte(uint32_t offset, uint8_t data); +extern void EepromWriteWord(uint32_t offset, uint16_t data); + +#endif // __EEPROM_H__ -- 2.20.1