]> Shamusworld >> Repos - virtualjaguar/commitdiff
Added Memory Track support. One small step towards full CD-ROM support.
authorShamus Hammons <jlhamm@acm.org>
Tue, 14 Jun 2016 03:36:06 +0000 (22:36 -0500)
committerShamus Hammons <jlhamm@acm.org>
Tue, 14 Jun 2016 03:36:06 +0000 (22:36 -0500)
12 files changed:
jaguarcore.mak
src/cdintf.cpp
src/cdintf.h
src/cdrom.cpp
src/eeprom.cpp
src/file.cpp
src/jaguar.cpp
src/jerry.cpp
src/memtrack.cpp [new file with mode: 0644]
src/memtrack.h [new file with mode: 0644]
src/tom.cpp
src/tom.h

index 9d44b4193375c4a5c5451b8d7482c12b00bb49ee..a90bb18fdacb697422741da08eafd402b6a22a23 100644 (file)
@@ -71,6 +71,7 @@ OBJS := \
        obj/joystick.o     \
        obj/log.o          \
        obj/memory.o       \
+       obj/memtrack.o     \
        obj/mmu.o          \
        obj/op.o           \
        obj/settings.o     \
index 45b6be2eac3aecfa510dfa2f05c1e10789be3653..1cf2ee2e2d728d9eadc9a103e999a08f67ab5674 100644 (file)
@@ -7,7 +7,7 @@
 // JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  ------------------------------------------------------------
 // JLH  01/16/2010  Created this log ;-)
 //
 
@@ -59,6 +59,7 @@ static void TestCDIO(void)
 static CdIo_t * cdioPtr = NULL;
 #endif
 
+
 bool CDIntfInit(void)
 {
 #ifdef HAVE_LIB_CDIO
@@ -78,6 +79,7 @@ bool CDIntfInit(void)
 #endif
 }
 
+
 void CDIntfDone(void)
 {
        WriteLog("CDINTF: Shutting down CD-ROM subsystem.\n");
@@ -88,6 +90,7 @@ void CDIntfDone(void)
 #endif
 }
 
+
 bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
 {
 #warning "!!! FIX !!! CDIntfReadBlock not implemented!"
@@ -96,6 +99,7 @@ bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
        return false;
 }
 
+
 uint32_t CDIntfGetNumSessions(void)
 {
 #warning "!!! FIX !!! CDIntfGetNumSessions not implemented!"
@@ -104,6 +108,7 @@ uint32_t CDIntfGetNumSessions(void)
        return 2;
 }
 
+
 void CDIntfSelectDrive(uint32_t driveNum)
 {
 #warning "!!! FIX !!! CDIntfSelectDrive not implemented!"
@@ -111,6 +116,7 @@ void CDIntfSelectDrive(uint32_t driveNum)
        WriteLog("CDINTF: SelectDrive unimplemented!\n");
 }
 
+
 uint32_t CDIntfGetCurrentDrive(void)
 {
 #warning "!!! FIX !!! CDIntfGetCurrentDrive not implemented!"
@@ -119,6 +125,7 @@ uint32_t CDIntfGetCurrentDrive(void)
        return 0;
 }
 
+
 const uint8_t * CDIntfGetDriveName(uint32_t driveNum)
 {
 #warning "!!! FIX !!! CDIntfGetDriveName driveNum is currently ignored!"
@@ -134,6 +141,7 @@ const uint8_t * CDIntfGetDriveName(uint32_t driveNum)
 #endif
 }
 
+
 uint8_t CDIntfGetSessionInfo(uint32_t session, uint32_t offset)
 {
 #warning "!!! FIX !!! CDIntfGetSessionInfo not implemented!"
@@ -142,6 +150,7 @@ uint8_t CDIntfGetSessionInfo(uint32_t session, uint32_t offset)
        return 0xFF;
 }
 
+
 uint8_t CDIntfGetTrackInfo(uint32_t track, uint32_t offset)
 {
 #warning "!!! FIX !!! CDIntfTrackInfo not implemented!"
@@ -149,3 +158,4 @@ uint8_t CDIntfGetTrackInfo(uint32_t track, uint32_t offset)
        WriteLog("CDINTF: GetTrackInfo unimplemented!\n");
        return 0xFF;
 }
+
index 530f3a87692c3c44ca0f6e0388d4a960a22a4262..83c021b1e596f2c3db87f2c90698ddfcb84b9fd9 100644 (file)
@@ -1,7 +1,7 @@
 //
 // CDINTF.H: OS agnostic CDROM access funcions
 //
-// by James L. Hammons
+// by James Hammons
 //
 
 #ifndef __CDINTF_H__
index a984c203b1331565ac3dd328cc2c6858c141f990..40d6daf1c0cdda0814c3dde4048809ba761bcaed 100644 (file)
@@ -9,7 +9,7 @@
 // JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  ------------------------------------------------------------
 // JLH  01/16/2010  Created this log ;-)
 //
 
@@ -172,8 +172,9 @@ static uint16_t CDROMBusRead(void);
 #define I2SDAT2                BUTCH + 0x28            // i2s FIFO data (old)
 #define UNKNOWN                BUTCH + 0x2C            // Seems to be some sort of I2S interface
 
-const char * BReg[12] = { "BUTCH", "DSCNTRL", "DS_DATA", "???", "I2CNTRL", "SBCNTRL", "SUBDATA", "SUBDATB",
-       "SB_TIME", "FIFO_DATA", "I2SDAT2", "UNKNOWN" };
+const char * BReg[12] = { "BUTCH", "DSCNTRL", "DS_DATA", "???", "I2CNTRL",
+       "SBCNTRL", "SUBDATA", "SUBDATB", "SB_TIME", "FIFO_DATA", "I2SDAT2",
+       "UNKNOWN" };
 //extern const char * whoName[9];
 
 
index 2fb896e44b6d229e4745ff6fa272544fcca89276..66c4a4c2da56c7b6dc5c87ad9bc86ff9b2ec40eb 100644 (file)
@@ -9,7 +9,7 @@
 // JLH = James Hammons <jlhamm@acm.org>
 //
 // Who  When        What
-// ---  ----------  -------------------------------------------------------------
+// ---  ----------  ------------------------------------------------------------
 // JLH  01/16/2010  Created this log ;-)
 //
 
@@ -63,6 +63,13 @@ 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);
@@ -141,7 +148,7 @@ static void EEPROMSave(void)
 void ReadEEPROMFromFile(FILE * file, uint16_t * ram)
 {
        uint8_t buffer[128];
-       fread(buffer, 1, 128, file);
+       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];
index 4586245656f9e9b4832299bed7ea44c100cb20e6..4262297a4094148f7db3d7857570f871c3dc9b2e 100644 (file)
@@ -48,7 +48,7 @@ uint32_t JaguarLoadROM(uint8_t * &rom, char * path)
 #warning "!!! FIX !!! Should have sanity checking for ROM size to prevent buffer overflow!"
        uint32_t romSize = 0;
 
-       WriteLog("JaguarLoadROM: Attempting to load file '%s'...", path);
+       WriteLog("FILE: JaguarLoadROM attempting to load file '%s'...", path);
        char * ext = strrchr(path, '.');
 
        // No filename extension == YUO FAIL IT (it is loading the file).
@@ -60,8 +60,8 @@ uint32_t JaguarLoadROM(uint8_t * &rom, char * path)
                return 0;
        }
 
-       WriteLog("Succeeded in finding extension (%s)!\n", ext);
-       WriteLog("VJ: Loading \"%s\"...", path);
+       WriteLog("\nFILE: Succeeded in finding extension (%s)!\n", ext);
+       WriteLog("FILE: Loading \"%s\"...", path);
 
        if (strcasecmp(ext, ".zip") == 0)
        {
@@ -277,7 +277,7 @@ bool AlpineLoadFile(char * path)
        }
 
        jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize);
-       WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32);
+       WriteLog("FILE: CRC is %08X\n", (unsigned int)jaguarMainROMCRC32);
        EepromInit();
 
        jaguarRunAddress = 0x802000;
index 4d96dca88df6c9ef64d296b6e741f974e0a87379..f829892333e69db0c91109ae100b92c61b10b455 100644 (file)
@@ -32,6 +32,7 @@
 #include "log.h"
 #include "m68000/m68kinterface.h"
 //#include "memory.h"
+#include "memtrack.h"
 #include "mmu.h"
 #include "settings.h"
 #include "tom.h"
@@ -1163,7 +1164,16 @@ unsigned int m68k_read_memory_16(unsigned int address)
                retVal = GET16(jaguarMainRAM, address);
 //     else if ((address >= 0x800000) && (address <= 0xDFFFFE))
        else if ((address >= 0x800000) && (address <= 0xDFFEFE))
-               retVal = (jaguarMainROM[address - 0x800000] << 8) | jaguarMainROM[address - 0x800000 + 1];
+       {
+               // Memory Track reading...
+               if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
+               {
+                       retVal = MTReadWord(address);
+               }
+               else
+                       retVal = (jaguarMainROM[address - 0x800000] << 8)
+                               | jaguarMainROM[address - 0x800000 + 1];
+       }
        else if ((address >= 0xE00000) && (address <= 0xE3FFFE))
 //             retVal = (jaguarBootROM[address - 0xE00000] << 8) | jaguarBootROM[address - 0xE00000 + 1];
 //             retVal = (jaguarDevBootROM1[address - 0xE00000] << 8) | jaguarDevBootROM1[address - 0xE00000 + 1];
@@ -1208,7 +1218,20 @@ unsigned int m68k_read_memory_32(unsigned int address)
 
 //WriteLog("--> [RM32]\n");
 #ifndef USE_NEW_MMU
-    return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
+       uint32_t retVal = 0;
+
+       if ((address >= 0x800000) && (address <= 0xDFFEFE))
+       {
+               // Memory Track reading...
+               if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
+                       retVal = MTReadLong(address);
+               else
+                       retVal = GET32(jaguarMainROM, address - 0x800000);
+
+               return retVal;
+       }
+
+       return (m68k_read_memory_16(address) << 16) | m68k_read_memory_16(address + 2);
 #else
        return MMURead32(address, M68K);
 #endif
@@ -1346,6 +1369,12 @@ if (address == 0xF02110)
                jaguar_mainRam[address + 1] = value & 0xFF;*/
                SET16(jaguarMainRAM, address, value);
        }
+       // Memory Track device writes....
+       else if ((address >= 0x800000) && (address <= 0x87FFFE))
+       {
+               if (((TOMGetMEMCON1() & 0x0006) == (2 << 1)) && (jaguarMainROMCRC32 == 0xFDF37F47))
+                       MTWriteWord(address, value);
+       }
        else if ((address >= 0xDFFF00) && (address <= 0xDFFFFE))
                CDROMWriteWord(address, value, M68K);
        else if ((address >= 0xF00000) && (address <= 0xF0FFFE))
index 32f8c92c85582af67ad833d3e9aefd8dc2037bac..1e2478fbbd074e654fd2ae4bda44b82be303a2a4 100644 (file)
 #include "joystick.h"
 #include "log.h"
 #include "m68000/m68kinterface.h"
+#include "memtrack.h"
 #include "settings.h"
 #include "tom.h"
 //#include "memory.h"
@@ -358,6 +359,7 @@ void JERRYI2SCallback(void)
 void JERRYInit(void)
 {
        JoystickInit();
+       MTInit();
        memcpy(&jerry_ram_8[0xD000], waveTableROM, 0x1000);
 
        JERRYPIT1Prescaler = 0xFFFF;
@@ -375,6 +377,7 @@ void JERRYReset(void)
 {
        JoystickReset();
        EepromReset();
+       MTReset();
        JERRYResetI2S();
 
        memset(jerry_ram_8, 0x00, 0xD000);              // Don't clear out the Wavetable ROM...!
@@ -398,6 +401,7 @@ void JERRYDone(void)
        JoystickDone();
        DACDone();
        EepromDone();
+       MTDone();
 }
 
 
diff --git a/src/memtrack.cpp b/src/memtrack.cpp
new file mode 100644 (file)
index 0000000..cc9daab
--- /dev/null
@@ -0,0 +1,225 @@
+//
+// Memory Track cartridge emulation
+//
+// by James Hammons
+// (C) 2016 Underground Software
+//
+// The Memory Track is just a large(-ish) EEPROM, holding 128K. We emulate the
+// Atmel part, since it seems to be easier to deal with than the AMD part. The
+// way it works is the 68K checks in its R/W functions to see if the MT is
+// inserted, and, if so, call the R/W functions here. It also checks to see if
+// the ROM width was changed to 32-bit; if not, then it reads the normal ROM in
+// the ROM space like usual.
+//
+// The Atmel part reads/writes a single byte into a long space. So we have to
+// adjust for that when reading from/writing to the NVRAM.
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who  When        What
+// ---  ----------  -----------------------------------------------------------
+// JLH  06/12/2016  Created this file ;-)
+//
+
+#include "memtrack.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <log.h>
+#include <settings.h>
+
+
+#define MEMTRACK_FILENAME      "memtrack.eeprom"
+//#define DEBUG_MEMTRACK
+
+enum { MT_NONE, MT_PROD_ID, MT_RESET, MT_WRITE_ENABLE };
+enum { MT_IDLE, MT_PHASE1, MT_PHASE2 };
+
+uint8_t mtMem[0x20000];
+uint8_t mtCommand = MT_NONE;
+uint8_t mtState = MT_IDLE;
+bool haveMT = false;
+char mtFilename[MAX_PATH];
+
+// Private function prototypes
+void MTWriteFile(void);
+void MTStateMachine(uint8_t reg, uint16_t data);
+
+
+void MTInit(void)
+{
+       sprintf(mtFilename, "%s%s", vjs.EEPROMPath, MEMTRACK_FILENAME);
+       FILE * fp = fopen(mtFilename, "rb");
+
+       if (fp)
+       {
+               size_t ignored = fread(mtMem, 1, 0x20000, fp);
+               fclose(fp);
+               WriteLog("MT: Loaded NVRAM from %s\n", mtFilename);
+               haveMT = true;
+       }
+       else
+               WriteLog("MT: Could not open file \"%s\"!\n", mtFilename);
+}
+
+
+void MTReset(void)
+{
+       if (!haveMT)
+               memset(mtMem, 0xFF, 0x20000);
+}
+
+
+void MTDone(void)
+{
+       MTWriteFile();
+       WriteLog("MT: Done.\n");
+}
+
+
+void MTWriteFile(void)
+{
+       if (!haveMT)
+               return;
+
+       FILE * fp = fopen(mtFilename, "wb");
+
+       if (fp)
+       {
+               fwrite(mtMem, 1, 0x20000, fp);
+               fclose(fp);
+       }
+       else
+               WriteLog("MT: Could not create file \"%s\"!", mtFilename);
+}
+
+
+//
+// This is crappy, there doesn't seem to be a word interface to the NVRAM. But
+// we'll keep this as a placeholder for now.
+//
+uint16_t MTReadWord(uint32_t addr)
+{
+       uint32_t value = MTReadLong(addr);
+
+       if ((addr & 0x03) == 0)
+               value >>= 16;
+       else if ((addr & 0x03) == 2)
+               value &= 0xFFFF;
+
+#ifdef DEBUG_MEMTRACK
+WriteLog("MT: Reading word @ $%06X: $%04X\n", addr, value);
+#endif
+
+       return (uint16_t)value;
+}
+
+
+uint32_t MTReadLong(uint32_t addr)
+{
+       uint32_t value = 0;
+
+       if (mtCommand == MT_PROD_ID)
+       {
+               if (addr == 0x800000)
+                       value = 0x1F;
+               else if (addr == 0x800004)
+                       value = 0xD5;
+       }
+       else
+       {
+               value = (uint32_t)mtMem[(addr & 0x7FFFC) >> 2];
+       }
+
+       // We do this because we're not sure how the real thing behaves; but it
+       // seems reasonable on its face to do it this way. :-P So we turn off write
+       // mode when reading the NVRAM.
+       if (mtCommand == MT_WRITE_ENABLE)
+               mtCommand = MT_NONE;
+
+#ifdef DEBUG_MEMTRACK
+WriteLog("MT: Reading long @ $%06X: $%08X\n", addr, value << 16);
+#endif
+       return value << 16;
+}
+
+
+void MTWriteWord(uint32_t addr, uint16_t data)
+{
+       // We don't care about writes to long offsets + 2
+       if ((addr & 0x3) == 2)
+               return;
+
+#ifdef DEBUG_MEMTRACK
+WriteLog("MT: Writing word @ $%06X: $%04X (Writing is %sabled)\n", addr, data, (mtCommand == MT_WRITE_ENABLE ? "en" : "dis"));
+#endif
+
+       // Write to the NVRAM if it's enabled...
+       if (mtCommand == MT_WRITE_ENABLE)
+       {
+               mtMem[(addr & 0x7FFFC) >> 2] = (uint8_t)(data & 0xFF);
+               return;
+       }
+
+       switch (addr)
+       {
+       case (0x800000 + (4 * 0x5555)):         // $815554
+               MTStateMachine(0, data);
+               break;
+       case (0x800000 + (4 * 0x2AAA)):         // $80AAA8
+               MTStateMachine(1, data);
+               break;
+       }
+}
+
+
+void MTWriteLong(uint32_t addr, uint32_t data)
+{
+       // Strip off lower 3 bits of the passed in address
+       addr &= 0xFFFFFC;
+
+       MTWriteWord(addr + 0, data & 0xFFFF);
+       MTWriteWord(addr + 2, data >> 16);
+}
+
+
+void MTStateMachine(uint8_t reg, uint16_t data)
+{
+#ifdef DEBUG_MEMTRACK
+WriteLog("MTStateMachine: reg = %u, data = $%02X, current state = %u\n", reg, data, mtState);
+#endif
+       switch (mtState)
+       {
+       case MT_IDLE:
+               if ((reg == 0) && (data == 0xAA))
+                       mtState = MT_PHASE1;
+
+               break;
+       case MT_PHASE1:
+               if ((reg == 1) && (data == 0x55))
+                       mtState = MT_PHASE2;
+               else
+                       mtState = MT_IDLE;
+
+               break;
+       case MT_PHASE2:
+               if (reg == 0)
+               {
+                       if (data == 0x90)               // Product ID
+                               mtCommand = MT_PROD_ID;
+                       else if (data == 0xF0)  // Reset
+                               mtCommand = MT_NONE;
+                       else if (data == 0xA0)  // Write enagle
+                               mtCommand = MT_WRITE_ENABLE;
+                       else
+                               mtCommand = MT_NONE;
+               }
+
+               mtState = MT_IDLE;
+               break;
+       }
+#ifdef DEBUG_MEMTRACK
+WriteLog("                state = %u, cmd = %u\n", mtState, mtCommand);
+#endif
+}
+
diff --git a/src/memtrack.h b/src/memtrack.h
new file mode 100644 (file)
index 0000000..d6eb036
--- /dev/null
@@ -0,0 +1,15 @@
+//
+// memtrack.h: Header file
+//
+
+#include <stdint.h>
+
+void MTInit(void);
+void MTReset(void);
+void MTDone(void);
+
+uint16_t MTReadWord(uint32_t addr);
+uint32_t MTReadLong(uint32_t addr);
+void MTWriteWord(uint32_t addr, uint16_t data);
+void MTWriteLong(uint32_t addr, uint32_t data);
+
index 3d6243b9212af862a2459d14c415ba2f62e64f83..6de61169c51bd81910cc183278b2c832a7bf001c 100644 (file)
@@ -652,6 +652,12 @@ uint16_t TOMGetVP(void)
 }
 
 
+uint16_t TOMGetMEMCON1(void)
+{
+       return GET16(tomRam8, MEMCON1);
+}
+
+
 #define LEFT_BG_FIX
 //
 // 16 BPP CRY/RGB mixed mode rendering
index 8c5640a3d697589c52820e2f89d6a446d8ee9846..4ac5736b4192a43eb22767c3be1fd67002c98002 100644 (file)
--- a/src/tom.h
+++ b/src/tom.h
@@ -43,6 +43,7 @@ uint16_t TOMGetHDB(void);
 uint16_t TOMGetVDB(void);
 uint16_t TOMGetHC(void);
 uint16_t TOMGetVP(void);
+uint16_t TOMGetMEMCON1(void);
 void TOMDumpIORegistersToLog(void);