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-2019 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 | |
18 | #include "Settings.hxx" |
19 | #include "Debugger.hxx" |
20 | #include "CartDebug.hxx" |
21 | #include "DiStella.hxx" |
22 | #include "CpuDebug.hxx" |
23 | #include "GuiObject.hxx" |
24 | #include "Font.hxx" |
25 | #include "DataGridWidget.hxx" |
26 | #include "EditTextWidget.hxx" |
27 | #include "PopUpWidget.hxx" |
28 | #include "ContextMenu.hxx" |
29 | #include "RomListWidget.hxx" |
30 | #include "RomWidget.hxx" |
31 | |
32 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
33 | RomWidget::RomWidget(GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, |
34 | int x, int y, int w, int h) |
35 | : Widget(boss, lfont, x, y, w, h), |
36 | CommandSender(boss), |
37 | myListIsDirty(true) |
38 | { |
39 | int xpos, ypos; |
40 | StaticTextWidget* t; |
41 | WidgetArray wid; |
42 | |
43 | // Show current bank state |
44 | xpos = x; ypos = y + 7; |
45 | t = new StaticTextWidget(boss, lfont, xpos, ypos, |
46 | lfont.getStringWidth("Bank" ), |
47 | lfont.getFontHeight(), |
48 | "Bank" , TextAlign::Left); |
49 | |
50 | xpos += t->getWidth() + 5; |
51 | myBank = new EditTextWidget(boss, nfont, xpos, ypos-2, |
52 | _w - 2 - xpos, nfont.getLineHeight()); |
53 | myBank->setEditable(false); |
54 | |
55 | // Create rom listing |
56 | xpos = x; ypos += myBank->getHeight() + 4; |
57 | |
58 | myRomList = new RomListWidget(boss, lfont, nfont, xpos, ypos, _w - 4, _h - ypos - 2); |
59 | myRomList->setTarget(this); |
60 | addFocusWidget(myRomList); |
61 | } |
62 | |
63 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
64 | void RomWidget::loadConfig() |
65 | { |
66 | Debugger& dbg = instance().debugger(); |
67 | CartDebug& cart = dbg.cartDebug(); |
68 | const CartState& state = static_cast<const CartState&>(cart.getState()); |
69 | const CartState& oldstate = static_cast<const CartState&>(cart.getOldState()); |
70 | |
71 | // Fill romlist the current bank of source or disassembly |
72 | myListIsDirty |= cart.disassemble(myListIsDirty); |
73 | if(myListIsDirty) |
74 | { |
75 | myRomList->setList(cart.disassembly()); |
76 | myListIsDirty = false; |
77 | } |
78 | |
79 | // Update romlist to point to current PC (if it has changed) |
80 | int pcline = cart.addressToLine(dbg.cpuDebug().pc()); |
81 | if(pcline >= 0 && pcline != myRomList->getHighlighted()) |
82 | myRomList->setHighlighted(pcline); |
83 | |
84 | // Set current bank state |
85 | myBank->setText(state.bank, state.bank != oldstate.bank); |
86 | } |
87 | |
88 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
89 | void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) |
90 | { |
91 | switch(cmd) |
92 | { |
93 | case RomListWidget::kBPointChangedCmd: |
94 | // 'data' is the line in the disassemblylist to be accessed |
95 | toggleBreak(data); |
96 | // Refresh the romlist, since the breakpoint may not have |
97 | // actually changed |
98 | myRomList->setDirty(); |
99 | myRomList->draw(); |
100 | break; |
101 | |
102 | case RomListWidget::kRomChangedCmd: |
103 | // 'data' is the line in the disassemblylist to be accessed |
104 | // 'id' is the base to use for the data to be changed |
105 | patchROM(data, myRomList->getText(), Common::Base::Format(id)); |
106 | break; |
107 | |
108 | case RomListWidget::kSetPCCmd: |
109 | // 'data' is the line in the disassemblylist to be accessed |
110 | setPC(data); |
111 | break; |
112 | |
113 | case RomListWidget::kRuntoPCCmd: |
114 | // 'data' is the line in the disassemblylist to be accessed |
115 | runtoPC(data); |
116 | break; |
117 | |
118 | case RomListWidget::kDisassembleCmd: |
119 | invalidate(); |
120 | break; |
121 | |
122 | case RomListWidget::kTentativeCodeCmd: |
123 | { |
124 | // 'data' is the boolean value |
125 | DiStella::settings.resolveCode = data; |
126 | instance().settings().setValue("dis.resolve" , |
127 | DiStella::settings.resolveCode); |
128 | invalidate(); |
129 | break; |
130 | } |
131 | |
132 | case RomListWidget::kPCAddressesCmd: |
133 | // 'data' is the boolean value |
134 | DiStella::settings.showAddresses = data; |
135 | instance().settings().setValue("dis.showaddr" , |
136 | DiStella::settings.showAddresses); |
137 | invalidate(); |
138 | break; |
139 | |
140 | case RomListWidget::kGfxAsBinaryCmd: |
141 | // 'data' is the boolean value |
142 | if(data) |
143 | { |
144 | DiStella::settings.gfxFormat = Common::Base::F_2; |
145 | instance().settings().setValue("dis.gfxformat" , "2" ); |
146 | } |
147 | else |
148 | { |
149 | DiStella::settings.gfxFormat = Common::Base::F_16; |
150 | instance().settings().setValue("dis.gfxformat" , "16" ); |
151 | } |
152 | invalidate(); |
153 | break; |
154 | |
155 | case RomListWidget::kAddrRelocationCmd: |
156 | // 'data' is the boolean value |
157 | DiStella::settings.rFlag = data; |
158 | instance().settings().setValue("dis.relocate" , |
159 | DiStella::settings.rFlag); |
160 | invalidate(); |
161 | break; |
162 | } |
163 | } |
164 | |
165 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
166 | void RomWidget::toggleBreak(int disasm_line) |
167 | { |
168 | const CartDebug::DisassemblyList& list = |
169 | instance().debugger().cartDebug().disassembly().list; |
170 | if(disasm_line >= int(list.size())) return; |
171 | |
172 | if(list[disasm_line].address != 0 && list[disasm_line].bytes != "" ) |
173 | instance().debugger().toggleBreakPoint(list[disasm_line].address, |
174 | instance().debugger().cartDebug().getBank(list[disasm_line].address)); |
175 | } |
176 | |
177 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
178 | void RomWidget::setPC(int disasm_line) |
179 | { |
180 | const CartDebug::DisassemblyList& list = |
181 | instance().debugger().cartDebug().disassembly().list; |
182 | if(disasm_line >= int(list.size())) return; |
183 | |
184 | if(list[disasm_line].address != 0) |
185 | { |
186 | ostringstream command; |
187 | command << "pc #" << list[disasm_line].address; |
188 | instance().debugger().run(command.str()); |
189 | } |
190 | } |
191 | |
192 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
193 | void RomWidget::runtoPC(int disasm_line) |
194 | { |
195 | const CartDebug::DisassemblyList& list = |
196 | instance().debugger().cartDebug().disassembly().list; |
197 | if(disasm_line >= int(list.size())) return; |
198 | |
199 | if(list[disasm_line].address != 0) |
200 | { |
201 | ostringstream command; |
202 | command << "runtopc #" << list[disasm_line].address; |
203 | instance().debugger().run(command.str()); |
204 | } |
205 | } |
206 | |
207 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
208 | void RomWidget::patchROM(int disasm_line, const string& bytes, |
209 | Common::Base::Format base) |
210 | { |
211 | const CartDebug::DisassemblyList& list = |
212 | instance().debugger().cartDebug().disassembly().list; |
213 | if(disasm_line >= int(list.size())) return; |
214 | |
215 | if(list[disasm_line].address != 0) |
216 | { |
217 | ostringstream command; |
218 | |
219 | // Temporarily set to correct base, so we don't have to prefix each byte |
220 | // with the type of data |
221 | Common::Base::Format oldbase = Common::Base::format(); |
222 | |
223 | Common::Base::setFormat(base); |
224 | command << "rom #" << list[disasm_line].address << " " << bytes; |
225 | instance().debugger().run(command.str()); |
226 | |
227 | // Restore previous base |
228 | Common::Base::setFormat(oldbase); |
229 | } |
230 | } |
231 | |
232 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
233 | void RomWidget::scrollTo(int line) |
234 | { |
235 | myRomList->setSelected(line); |
236 | } |
237 | |