Debugger sources code clean-up
[clinton/Virtual-Jaguar-Rx.git] / src / memtrack.cpp
CommitLineData
cf76e892
JPM
1//
2// Memory Track cartridge emulation
3//
4// by James Hammons
5// (C) 2016 Underground Software
6//
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.
13//
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.
16//
17// JLH = James Hammons <jlhamm@acm.org>
18// JPM = Jean-Paul Mari <djipi.mari@gmail.com>
19//
20// Who When What
21// --- ---------- -----------------------------------------------------------
22// JLH 06/12/2016 Created this file ;-)
23// JPM 06/06/2016 Visual Studio support
24//
25
26#include "memtrack.h"
27
28#include <stdlib.h>
29#include <string.h>
30#include "log.h" // JPM: changed <log.h> to "log.h"
31#include "settings.h" // JPM: changed <settings.h> to "settings.h"
32
33
34#define MEMTRACK_FILENAME "memtrack.eeprom"
35//#define DEBUG_MEMTRACK
36
37enum { MT_NONE, MT_PROD_ID, MT_RESET, MT_WRITE_ENABLE };
38enum { MT_IDLE, MT_PHASE1, MT_PHASE2 };
39
40uint8_t mtMem[0x20000];
41uint8_t mtCommand = MT_NONE;
42uint8_t mtState = MT_IDLE;
43bool haveMT = false;
44char mtFilename[MAX_PATH];
45
46// Private function prototypes
47void MTWriteFile(void);
48void MTStateMachine(uint8_t reg, uint16_t data);
49
50
51void MTInit(void)
52{
53 sprintf(mtFilename, "%s%s", vjs.EEPROMPath, MEMTRACK_FILENAME);
54 FILE * fp = fopen(mtFilename, "rb");
55
56 if (fp)
57 {
58 size_t ignored = fread(mtMem, 1, 0x20000, fp);
59 fclose(fp);
60 WriteLog("MT: Loaded NVRAM from %s\n", mtFilename);
61 haveMT = true;
62 }
63 else
64 WriteLog("MT: Could not open file \"%s\"!\n", mtFilename);
65}
66
67
68void MTReset(void)
69{
70 if (!haveMT)
71 memset(mtMem, 0xFF, 0x20000);
72}
73
74
75void MTDone(void)
76{
77 MTWriteFile();
78 WriteLog("MT: Done.\n");
79}
80
81
82void MTWriteFile(void)
83{
84 if (!haveMT)
85 return;
86
87 FILE * fp = fopen(mtFilename, "wb");
88
89 if (fp)
90 {
91 fwrite(mtMem, 1, 0x20000, fp);
92 fclose(fp);
93 }
94 else
95 WriteLog("MT: Could not create file \"%s\"!", mtFilename);
96}
97
98
99//
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.
102//
103uint16_t MTReadWord(uint32_t addr)
104{
105 uint32_t value = MTReadLong(addr);
106
107 if ((addr & 0x03) == 0)
108 value >>= 16;
109 else if ((addr & 0x03) == 2)
110 value &= 0xFFFF;
111
112#ifdef DEBUG_MEMTRACK
113WriteLog("MT: Reading word @ $%06X: $%04X\n", addr, value);
114#endif
115
116 return (uint16_t)value;
117}
118
119
120uint32_t MTReadLong(uint32_t addr)
121{
122 uint32_t value = 0;
123
124 if (mtCommand == MT_PROD_ID)
125 {
126 if (addr == 0x800000)
127 value = 0x1F;
128 else if (addr == 0x800004)
129 value = 0xD5;
130 }
131 else
132 {
133 value = (uint32_t)mtMem[(addr & 0x7FFFC) >> 2];
134 }
135
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)
140 mtCommand = MT_NONE;
141
142#ifdef DEBUG_MEMTRACK
143WriteLog("MT: Reading long @ $%06X: $%08X\n", addr, value << 16);
144#endif
145 return value << 16;
146}
147
148
149void MTWriteWord(uint32_t addr, uint16_t data)
150{
151 // We don't care about writes to long offsets + 2
152 if ((addr & 0x3) == 2)
153 return;
154
155#ifdef DEBUG_MEMTRACK
156WriteLog("MT: Writing word @ $%06X: $%04X (Writing is %sabled)\n", addr, data, (mtCommand == MT_WRITE_ENABLE ? "en" : "dis"));
157#endif
158
159 // Write to the NVRAM if it's enabled...
160 if (mtCommand == MT_WRITE_ENABLE)
161 {
162 mtMem[(addr & 0x7FFFC) >> 2] = (uint8_t)(data & 0xFF);
163 return;
164 }
165
166 switch (addr)
167 {
168 case (0x800000 + (4 * 0x5555)): // $815554
169 MTStateMachine(0, data);
170 break;
171 case (0x800000 + (4 * 0x2AAA)): // $80AAA8
172 MTStateMachine(1, data);
173 break;
174 }
175}
176
177
178void MTWriteLong(uint32_t addr, uint32_t data)
179{
180 // Strip off lower 3 bits of the passed in address
181 addr &= 0xFFFFFC;
182
183 MTWriteWord(addr + 0, data & 0xFFFF);
184 MTWriteWord(addr + 2, data >> 16);
185}
186
187
188void MTStateMachine(uint8_t reg, uint16_t data)
189{
190#ifdef DEBUG_MEMTRACK
191WriteLog("MTStateMachine: reg = %u, data = $%02X, current state = %u\n", reg, data, mtState);
192#endif
193 switch (mtState)
194 {
195 case MT_IDLE:
196 if ((reg == 0) && (data == 0xAA))
197 mtState = MT_PHASE1;
198
199 break;
200 case MT_PHASE1:
201 if ((reg == 1) && (data == 0x55))
202 mtState = MT_PHASE2;
203 else
204 mtState = MT_IDLE;
205
206 break;
207 case MT_PHASE2:
208 if (reg == 0)
209 {
210 if (data == 0x90) // Product ID
211 mtCommand = MT_PROD_ID;
212 else if (data == 0xF0) // Reset
213 mtCommand = MT_NONE;
214 else if (data == 0xA0) // Write enagle
215 mtCommand = MT_WRITE_ENABLE;
216 else
217 mtCommand = MT_NONE;
218 }
219
220 mtState = MT_IDLE;
221 break;
222 }
223#ifdef DEBUG_MEMTRACK
224WriteLog(" state = %u, cmd = %u\n", mtState, mtCommand);
225#endif
226}
227