1 //============================================================================
2 //
3 // SSSS tt lll lll
4 // SS SS tt ll ll
5 // SS tttttt eeee ll ll aaaa
6 // SSSS tt ee ee ll ll aa
7 // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8 // SS SS tt ee ll ll aa aa
9 // SSSS ttt eeeee llll llll aaaaa
10 //
11 // Copyright (c) 1995-2014 by Bradford W. Mott, Stephen Anthony
12 // and the Stella Team
13 //
14 // See the file "License.txt" for information on usage and redistribution of
15 // this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 //
17 // $Id: RiotDebug.cxx 2838 2014-01-17 23:34:03Z stephena $
18 //============================================================================
19
20 #include <sstream>
21
22 #include "System.hxx"
23 #include "TIA.hxx"
24 #include "Debugger.hxx"
25 #include "Switches.hxx"
26
27 #include "RiotDebug.hxx"
28
29 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RiotDebug(Debugger & dbg,Console & console)30 RiotDebug::RiotDebug(Debugger& dbg, Console& console)
31 : DebuggerSystem(dbg, console)
32 {
33 }
34
35 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
getState()36 const DebuggerState& RiotDebug::getState()
37 {
38 // Port A & B registers
39 myState.SWCHA_R = swcha();
40 myState.SWCHA_W = mySystem.m6532().myOutA;
41 myState.SWACNT = swacnt();
42 myState.SWCHB_R = swchb();
43 myState.SWCHB_W = mySystem.m6532().myOutB;
44 myState.SWBCNT = swbcnt();
45 Debugger::set_bits(myState.SWCHA_R, myState.swchaReadBits);
46 Debugger::set_bits(myState.SWCHA_W, myState.swchaWriteBits);
47 Debugger::set_bits(myState.SWACNT, myState.swacntBits);
48 Debugger::set_bits(myState.SWCHB_R, myState.swchbReadBits);
49 Debugger::set_bits(myState.SWCHB_W, myState.swchbWriteBits);
50 Debugger::set_bits(myState.SWBCNT, myState.swbcntBits);
51
52 // TIA INPTx registers
53 myState.INPT0 = inpt(0);
54 myState.INPT1 = inpt(1);
55 myState.INPT2 = inpt(2);
56 myState.INPT3 = inpt(3);
57 myState.INPT4 = inpt(4);
58 myState.INPT5 = inpt(5);
59
60 // Timer registers
61 myState.TIM1T = tim1T();
62 myState.TIM8T = tim8T();
63 myState.TIM64T = tim64T();
64 myState.T1024T = tim1024T();
65 myState.INTIM = intim();
66 myState.TIMINT = timint();
67 myState.TIMCLKS = timClocks();
68 myState.INTIMCLKS = intimClocks();
69
70 return myState;
71 }
72
73 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
saveOldState()74 void RiotDebug::saveOldState()
75 {
76 // Port A & B registers
77 myOldState.SWCHA_R = swcha();
78 myOldState.SWCHA_W = mySystem.m6532().myOutA;
79 myOldState.SWACNT = swacnt();
80 myOldState.SWCHB_R = swchb();
81 myOldState.SWCHB_W = mySystem.m6532().myOutB;
82 myOldState.SWBCNT = swbcnt();
83 Debugger::set_bits(myOldState.SWCHA_R, myOldState.swchaReadBits);
84 Debugger::set_bits(myOldState.SWCHA_W, myOldState.swchaWriteBits);
85 Debugger::set_bits(myOldState.SWACNT, myOldState.swacntBits);
86 Debugger::set_bits(myOldState.SWCHB_R, myOldState.swchbReadBits);
87 Debugger::set_bits(myOldState.SWCHB_W, myOldState.swchbWriteBits);
88 Debugger::set_bits(myOldState.SWBCNT, myOldState.swbcntBits);
89
90 // TIA INPTx registers
91 myOldState.INPT0 = inpt(0);
92 myOldState.INPT1 = inpt(1);
93 myOldState.INPT2 = inpt(2);
94 myOldState.INPT3 = inpt(3);
95 myOldState.INPT4 = inpt(4);
96 myOldState.INPT5 = inpt(5);
97
98 // Timer registers
99 myOldState.TIM1T = tim1T();
100 myOldState.TIM8T = tim8T();
101 myOldState.TIM64T = tim64T();
102 myOldState.T1024T = tim1024T();
103 myOldState.INTIM = intim();
104 myOldState.TIMINT = timint();
105 myOldState.TIMCLKS = timClocks();
106 myOldState.INTIMCLKS = intimClocks();
107 }
108
109 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
swcha(int newVal)110 uInt8 RiotDebug::swcha(int newVal)
111 {
112 if(newVal > -1)
113 mySystem.poke(0x280, newVal);
114
115 return mySystem.peek(0x280);
116 }
117
118 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
swchb(int newVal)119 uInt8 RiotDebug::swchb(int newVal)
120 {
121 if(newVal > -1)
122 mySystem.poke(0x282, newVal);
123
124 return mySystem.peek(0x282);
125 }
126
127 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
swacnt(int newVal)128 uInt8 RiotDebug::swacnt(int newVal)
129 {
130 if(newVal > -1)
131 mySystem.poke(0x281, newVal);
132
133 return mySystem.m6532().myDDRA;
134 }
135
136 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
swbcnt(int newVal)137 uInt8 RiotDebug::swbcnt(int newVal)
138 {
139 if(newVal > -1)
140 mySystem.poke(0x283, newVal);
141
142 return mySystem.m6532().myDDRB;
143 }
144
145 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inpt(int x)146 uInt8 RiotDebug::inpt(int x)
147 {
148 static TIARegister _inpt[6] = { INPT0, INPT1, INPT2, INPT3, INPT4, INPT5 };
149 return mySystem.peek(_inpt[x]);
150 }
151
152 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
vblank(int bit)153 bool RiotDebug::vblank(int bit)
154 {
155 if(bit == 6) // latches
156 return mySystem.tia().myVBLANK & 0x40;
157 else if(bit == 7) // dump to ground
158 return mySystem.tia().myDumpEnabled;
159 else
160 return true;
161 }
162
163
164 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tim1T(int newVal)165 uInt8 RiotDebug::tim1T(int newVal)
166 {
167 if(newVal > -1)
168 mySystem.poke(0x294, newVal);
169
170 return mySystem.m6532().myOutTimer[0];
171 }
172
173 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tim8T(int newVal)174 uInt8 RiotDebug::tim8T(int newVal)
175 {
176 if(newVal > -1)
177 mySystem.poke(0x295, newVal);
178
179 return mySystem.m6532().myOutTimer[1];
180 }
181
182 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tim64T(int newVal)183 uInt8 RiotDebug::tim64T(int newVal)
184 {
185 if(newVal > -1)
186 mySystem.poke(0x296, newVal);
187
188 return mySystem.m6532().myOutTimer[2];
189 }
190
191 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tim1024T(int newVal)192 uInt8 RiotDebug::tim1024T(int newVal)
193 {
194 if(newVal > -1)
195 mySystem.poke(0x297, newVal);
196
197 return mySystem.m6532().myOutTimer[3];
198 }
199
200 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
controller(Controller::Jack jack) const201 Controller& RiotDebug::controller(Controller::Jack jack) const
202 {
203 return myConsole.controller(jack);
204 }
205
206 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diffP0(int newVal)207 bool RiotDebug::diffP0(int newVal)
208 {
209 uInt8& switches = myConsole.switches().mySwitches;
210 if(newVal > -1)
211 switches = Debugger::set_bit(switches, 6, newVal > 0);
212
213 return switches & 0x40;
214 }
215
216 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diffP1(int newVal)217 bool RiotDebug::diffP1(int newVal)
218 {
219 uInt8& switches = myConsole.switches().mySwitches;
220 if(newVal > -1)
221 switches = Debugger::set_bit(switches, 7, newVal > 0);
222
223 return switches & 0x80;
224 }
225
226 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tvType(int newVal)227 bool RiotDebug::tvType(int newVal)
228 {
229 uInt8& switches = myConsole.switches().mySwitches;
230 if(newVal > -1)
231 switches = Debugger::set_bit(switches, 3, newVal > 0);
232
233 return switches & 0x08;
234 }
235
236 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
select(int newVal)237 bool RiotDebug::select(int newVal)
238 {
239 uInt8& switches = myConsole.switches().mySwitches;
240 if(newVal > -1)
241 switches = Debugger::set_bit(switches, 1, newVal > 0);
242
243 return switches & 0x02;
244 }
245
246 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
reset(int newVal)247 bool RiotDebug::reset(int newVal)
248 {
249 uInt8& switches = myConsole.switches().mySwitches;
250 if(newVal > -1)
251 switches = Debugger::set_bit(switches, 0, newVal > 0);
252
253 return switches & 0x01;
254 }
255
256 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dirP0String()257 string RiotDebug::dirP0String()
258 {
259 uInt8 reg = swcha();
260 ostringstream buf;
261 buf << (reg & 0x80 ? "" : "right ")
262 << (reg & 0x40 ? "" : "left ")
263 << (reg & 0x20 ? "" : "left ")
264 << (reg & 0x10 ? "" : "left ")
265 << ((reg & 0xf0) == 0xf0 ? "(no directions) " : "");
266 return buf.str();
267 }
268
269 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
dirP1String()270 string RiotDebug::dirP1String()
271 {
272 uInt8 reg = swcha();
273 ostringstream buf;
274 buf << (reg & 0x08 ? "" : "right ")
275 << (reg & 0x04 ? "" : "left ")
276 << (reg & 0x02 ? "" : "left ")
277 << (reg & 0x01 ? "" : "left ")
278 << ((reg & 0x0f) == 0x0f ? "(no directions) " : "");
279 return buf.str();
280 }
281
282 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diffP0String()283 string RiotDebug::diffP0String()
284 {
285 return (swchb() & 0x40) ? "hard/A" : "easy/B";
286 }
287
288 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diffP1String()289 string RiotDebug::diffP1String()
290 {
291 return (swchb() & 0x80) ? "hard/A" : "easy/B";
292 }
293
294 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tvTypeString()295 string RiotDebug::tvTypeString()
296 {
297 return (swchb() & 0x8) ? "Color" : "B&W";
298 }
299
300 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
switchesString()301 string RiotDebug::switchesString()
302 {
303 ostringstream buf;
304 buf << (swchb() & 0x2 ? "-" : "+") << "select "
305 << (swchb() & 0x1 ? "-" : "+") << "reset";
306 return buf.str();
307 }
308
309 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
toString()310 string RiotDebug::toString()
311 {
312 const RiotState& state = (RiotState&) getState();
313 const RiotState& oldstate = (RiotState&) getOldState();
314
315 ostringstream buf;
316 buf << "280/SWCHA(R)=" << myDebugger.invIfChanged(state.SWCHA_R, oldstate.SWCHA_R)
317 << " 280/SWCHA(W)=" << myDebugger.invIfChanged(state.SWCHA_W, oldstate.SWCHA_W)
318 << " 281/SWACNT=" << myDebugger.invIfChanged(state.SWACNT, oldstate.SWACNT)
319 << endl
320 << "282/SWCHB(R)=" << myDebugger.invIfChanged(state.SWCHB_R, oldstate.SWCHB_R)
321 << " 282/SWCHB(W)=" << myDebugger.invIfChanged(state.SWCHB_W, oldstate.SWCHB_W)
322 << " 283/SWBCNT=" << myDebugger.invIfChanged(state.SWBCNT, oldstate.SWBCNT)
323 << endl
324
325 // These are squirrely: some symbol files will define these as
326 // 0x284-0x287. Doesn't actually matter, these registers repeat
327 // every 16 bytes.
328 << "294/TIM1T=" << myDebugger.invIfChanged(state.TIM1T, oldstate.TIM1T)
329 << " 295/TIM8T=" << myDebugger.invIfChanged(state.TIM8T, oldstate.TIM8T)
330 << " 296/TIM64T=" << myDebugger.invIfChanged(state.TIM64T, oldstate.TIM64T)
331 << " 297/T1024T=" << myDebugger.invIfChanged(state.T1024T, oldstate.T1024T)
332 << endl
333
334 << "0x284/INTIM=" << myDebugger.invIfChanged(state.INTIM, oldstate.INTIM)
335 << " 285/TIMINT=" << myDebugger.invIfChanged(state.TIMINT, oldstate.TIMINT)
336 << " Timer_Clocks=" << myDebugger.invIfChanged(state.TIMCLKS, oldstate.TIMCLKS)
337 << " INTIM_Clocks=" << myDebugger.invIfChanged(state.INTIMCLKS, oldstate.INTIMCLKS)
338 << endl
339
340 << "Left/P0diff: " << diffP0String() << " Right/P1diff: " << diffP0String()
341 << endl
342 << "TVType: " << tvTypeString() << " Switches: " << switchesString()
343 << endl
344
345 // Yes, the fire buttons are in the TIA, but we might as well
346 // show them here for convenience.
347 << "Left/P0 stick: " << dirP0String()
348 << ((mySystem.peek(0x03c) & 0x80) ? "" : "(button) ")
349 << endl
350 << "Right/P1 stick: " << dirP1String()
351 << ((mySystem.peek(0x03d) & 0x80) ? "" : "(button) ");
352
353 return buf.str();
354 }
355