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