obj/joystick.o \
obj/log.o \
obj/memory.o \
+ obj/memtrack.o \
obj/mmu.o \
obj/op.o \
obj/settings.o \
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
-// --- ---------- -------------------------------------------------------------
+// --- ---------- ------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
//
static CdIo_t * cdioPtr = NULL;
#endif
+
bool CDIntfInit(void)
{
#ifdef HAVE_LIB_CDIO
#endif
}
+
void CDIntfDone(void)
{
WriteLog("CDINTF: Shutting down CD-ROM subsystem.\n");
#endif
}
+
bool CDIntfReadBlock(uint32_t sector, uint8_t * buffer)
{
#warning "!!! FIX !!! CDIntfReadBlock not implemented!"
return false;
}
+
uint32_t CDIntfGetNumSessions(void)
{
#warning "!!! FIX !!! CDIntfGetNumSessions not implemented!"
return 2;
}
+
void CDIntfSelectDrive(uint32_t driveNum)
{
#warning "!!! FIX !!! CDIntfSelectDrive not implemented!"
WriteLog("CDINTF: SelectDrive unimplemented!\n");
}
+
uint32_t CDIntfGetCurrentDrive(void)
{
#warning "!!! FIX !!! CDIntfGetCurrentDrive not implemented!"
return 0;
}
+
const uint8_t * CDIntfGetDriveName(uint32_t driveNum)
{
#warning "!!! FIX !!! CDIntfGetDriveName driveNum is currently ignored!"
#endif
}
+
uint8_t CDIntfGetSessionInfo(uint32_t session, uint32_t offset)
{
#warning "!!! FIX !!! CDIntfGetSessionInfo not implemented!"
return 0xFF;
}
+
uint8_t CDIntfGetTrackInfo(uint32_t track, uint32_t offset)
{
#warning "!!! FIX !!! CDIntfTrackInfo not implemented!"
WriteLog("CDINTF: GetTrackInfo unimplemented!\n");
return 0xFF;
}
+
//
// CDINTF.H: OS agnostic CDROM access funcions
//
-// by James L. Hammons
+// by James Hammons
//
#ifndef __CDINTF_H__
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
-// --- ---------- -------------------------------------------------------------
+// --- ---------- ------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
//
#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];
// JLH = James Hammons <jlhamm@acm.org>
//
// Who When What
-// --- ---------- -------------------------------------------------------------
+// --- ---------- ------------------------------------------------------------
// JLH 01/16/2010 Created this log ;-)
//
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);
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];
#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).
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)
{
}
jaguarMainROMCRC32 = crc32_calcCheckSum(buffer, jaguarROMSize);
- WriteLog("CRC: %08X\n", (unsigned int)jaguarMainROMCRC32);
+ WriteLog("FILE: CRC is %08X\n", (unsigned int)jaguarMainROMCRC32);
EepromInit();
jaguarRunAddress = 0x802000;
#include "log.h"
#include "m68000/m68kinterface.h"
//#include "memory.h"
+#include "memtrack.h"
#include "mmu.h"
#include "settings.h"
#include "tom.h"
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];
//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
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))
#include "joystick.h"
#include "log.h"
#include "m68000/m68kinterface.h"
+#include "memtrack.h"
#include "settings.h"
#include "tom.h"
//#include "memory.h"
void JERRYInit(void)
{
JoystickInit();
+ MTInit();
memcpy(&jerry_ram_8[0xD000], waveTableROM, 0x1000);
JERRYPIT1Prescaler = 0xFFFF;
{
JoystickReset();
EepromReset();
+ MTReset();
JERRYResetI2S();
memset(jerry_ram_8, 0x00, 0xD000); // Don't clear out the Wavetable ROM...!
JoystickDone();
DACDone();
EepromDone();
+ MTDone();
}
--- /dev/null
+//
+// 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
+}
+
--- /dev/null
+//
+// 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);
+
}
+uint16_t TOMGetMEMCON1(void)
+{
+ return GET16(tomRam8, MEMCON1);
+}
+
+
#define LEFT_BG_FIX
//
// 16 BPP CRY/RGB mixed mode rendering
uint16_t TOMGetVDB(void);
uint16_t TOMGetHC(void);
uint16_t TOMGetVP(void);
+uint16_t TOMGetMEMCON1(void);
void TOMDumpIORegistersToLog(void);