2 // Memory Track cartridge emulation
5 // (C) 2016 Underground Software
7 // The Memory Track is just a large(-ish) EEPROM, holding 128K. We emulate the
8 // Atmel part, since it seems to be easier to deal with than the AMD part. The
9 // way it works is the 68K checks in its R/W functions to see if the MT is
10 // inserted, and, if so, call the R/W functions here. It also checks to see if
11 // the ROM width was changed to 32-bit; if not, then it reads the normal ROM in
12 // the ROM space like usual.
14 // The Atmel part reads/writes a single byte into a long space. So we have to
15 // adjust for that when reading from/writing to the NVRAM.
17 // JLH = James Hammons <jlhamm@acm.org>
18 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
21 // --- ---------- -----------------------------------------------------------
22 // JLH 06/12/2016 Created this file ;-)
23 // JPM 06/06/2016 Visual Studio support
30 #include "log.h" // JPM: changed <log.h> to "log.h"
31 #include "settings.h" // JPM: changed <settings.h> to "settings.h"
34 #define MEMTRACK_FILENAME "memtrack.eeprom"
35 //#define DEBUG_MEMTRACK
37 enum { MT_NONE
, MT_PROD_ID
, MT_RESET
, MT_WRITE_ENABLE
};
38 enum { MT_IDLE
, MT_PHASE1
, MT_PHASE2
};
40 uint8_t mtMem
[0x20000];
41 uint8_t mtCommand
= MT_NONE
;
42 uint8_t mtState
= MT_IDLE
;
44 char mtFilename
[MAX_PATH
];
46 // Private function prototypes
47 void MTWriteFile(void);
48 void MTStateMachine(uint8_t reg
, uint16_t data
);
53 sprintf(mtFilename
, "%s%s", vjs
.EEPROMPath
, MEMTRACK_FILENAME
);
54 FILE * fp
= fopen(mtFilename
, "rb");
58 size_t ignored
= fread(mtMem
, 1, 0x20000, fp
);
60 WriteLog("MT: Loaded NVRAM from %s\n", mtFilename
);
64 WriteLog("MT: Could not open file \"%s\"!\n", mtFilename
);
71 memset(mtMem
, 0xFF, 0x20000);
78 WriteLog("MT: Done.\n");
82 void MTWriteFile(void)
87 FILE * fp
= fopen(mtFilename
, "wb");
91 fwrite(mtMem
, 1, 0x20000, fp
);
95 WriteLog("MT: Could not create file \"%s\"!", mtFilename
);
100 // This is crappy, there doesn't seem to be a word interface to the NVRAM. But
101 // we'll keep this as a placeholder for now.
103 uint16_t MTReadWord(uint32_t addr
)
105 uint32_t value
= MTReadLong(addr
);
107 if ((addr
& 0x03) == 0)
109 else if ((addr
& 0x03) == 2)
112 #ifdef DEBUG_MEMTRACK
113 WriteLog("MT: Reading word @ $%06X: $%04X\n", addr
, value
);
116 return (uint16_t)value
;
120 uint32_t MTReadLong(uint32_t addr
)
124 if (mtCommand
== MT_PROD_ID
)
126 if (addr
== 0x800000)
128 else if (addr
== 0x800004)
133 value
= (uint32_t)mtMem
[(addr
& 0x7FFFC) >> 2];
136 // We do this because we're not sure how the real thing behaves; but it
137 // seems reasonable on its face to do it this way. :-P So we turn off write
138 // mode when reading the NVRAM.
139 if (mtCommand
== MT_WRITE_ENABLE
)
142 #ifdef DEBUG_MEMTRACK
143 WriteLog("MT: Reading long @ $%06X: $%08X\n", addr
, value
<< 16);
149 void MTWriteWord(uint32_t addr
, uint16_t data
)
151 // We don't care about writes to long offsets + 2
152 if ((addr
& 0x3) == 2)
155 #ifdef DEBUG_MEMTRACK
156 WriteLog("MT: Writing word @ $%06X: $%04X (Writing is %sabled)\n", addr
, data
, (mtCommand
== MT_WRITE_ENABLE
? "en" : "dis"));
159 // Write to the NVRAM if it's enabled...
160 if (mtCommand
== MT_WRITE_ENABLE
)
162 mtMem
[(addr
& 0x7FFFC) >> 2] = (uint8_t)(data
& 0xFF);
168 case (0x800000 + (4 * 0x5555)): // $815554
169 MTStateMachine(0, data
);
171 case (0x800000 + (4 * 0x2AAA)): // $80AAA8
172 MTStateMachine(1, data
);
178 void MTWriteLong(uint32_t addr
, uint32_t data
)
180 // Strip off lower 3 bits of the passed in address
183 MTWriteWord(addr
+ 0, data
& 0xFFFF);
184 MTWriteWord(addr
+ 2, data
>> 16);
188 void MTStateMachine(uint8_t reg
, uint16_t data
)
190 #ifdef DEBUG_MEMTRACK
191 WriteLog("MTStateMachine: reg = %u, data = $%02X, current state = %u\n", reg
, data
, mtState
);
196 if ((reg
== 0) && (data
== 0xAA))
201 if ((reg
== 1) && (data
== 0x55))
210 if (data
== 0x90) // Product ID
211 mtCommand
= MT_PROD_ID
;
212 else if (data
== 0xF0) // Reset
214 else if (data
== 0xA0) // Write enagle
215 mtCommand
= MT_WRITE_ENABLE
;
223 #ifdef DEBUG_MEMTRACK
224 WriteLog(" state = %u, cmd = %u\n", mtState
, mtCommand
);