Commit | Line | Data |
---|---|---|
cf76e892 JPM |
1 | // |
2 | // opbrowser.cpp - Jaguar Object Processor browser | |
3 | // | |
4 | // by James Hammons | |
5 | // (C) 2012 Underground Software | |
6 | // | |
7 | // JLH = James Hammons <jlhamm@acm.org> | |
8 | // | |
9 | // Who When What | |
10 | // --- ---------- ----------------------------------------------------------- | |
11 | // JLH 12/01/2012 Created this file | |
12 | // | |
13 | ||
14 | // STILL TO DO: | |
15 | // | |
16 | ||
17 | #include "opbrowser.h" | |
18 | #include "jaguar.h" | |
19 | #include "memory.h" | |
20 | #include "op.h" | |
21 | ||
22 | ||
23 | OPBrowserWindow::OPBrowserWindow(QWidget * parent/*= 0*/): QWidget(parent, Qt::Dialog), | |
24 | layout(new QVBoxLayout), text(new QLabel), | |
25 | refresh(new QPushButton(tr("Refresh"))) | |
26 | { | |
27 | setWindowTitle(tr("OP Browser")); | |
28 | ||
29 | // Need to set the size as well... | |
30 | // resize(560, 480); | |
31 | ||
32 | QFont fixedFont("Lucida Console", 8, QFont::Normal); | |
33 | // QFont fixedFont("", 8, QFont::Normal); | |
34 | fixedFont.setStyleHint(QFont::TypeWriter); | |
35 | text->setFont(fixedFont); | |
36 | //// layout->setSizeConstraint(QLayout::SetFixedSize); | |
37 | setLayout(layout); | |
38 | ||
39 | QScrollArea * scrollArea = new QScrollArea; | |
40 | scrollArea->setWidgetResizable(true); | |
41 | scrollArea->setWidget(text); | |
42 | layout->addWidget(scrollArea); | |
43 | layout->addWidget(refresh); | |
44 | ||
45 | connect(refresh, SIGNAL(clicked()), this, SLOT(RefreshContents())); | |
46 | } | |
47 | ||
48 | ||
49 | void OPBrowserWindow::RefreshContents(void) | |
50 | { | |
51 | char string[1024];//, buf[64]; | |
52 | QString opDump; | |
53 | ||
54 | if (isVisible()) | |
55 | { | |
56 | uint32_t olp = OPGetListPointer(); | |
57 | sprintf(string, "OLP = $%X<br>", olp); | |
58 | opDump += QString(string); | |
59 | ||
60 | numberOfObjects = 0; | |
61 | DiscoverObjects(olp); | |
62 | DumpObjectList(opDump); | |
63 | ||
64 | text->clear(); | |
65 | text->setText(opDump); | |
66 | } | |
67 | } | |
68 | ||
69 | ||
70 | void OPBrowserWindow::keyPressEvent(QKeyEvent * e) | |
71 | { | |
72 | if (e->key() == Qt::Key_Escape) | |
73 | hide(); | |
74 | else if (e->key() == Qt::Key_Enter) | |
75 | RefreshContents(); | |
76 | } | |
77 | ||
78 | ||
79 | bool OPBrowserWindow::ObjectExists(uint32_t address) | |
80 | { | |
81 | // Yes, we really do a linear search, every time. :-/ | |
82 | for(uint32_t i=0; i<numberOfObjects; i++) | |
83 | { | |
84 | if (address == object[i]) | |
85 | return true; | |
86 | } | |
87 | ||
88 | return false; | |
89 | } | |
90 | ||
91 | ||
92 | void OPBrowserWindow::DiscoverObjects(uint32_t address) | |
93 | { | |
94 | uint8_t objectType = 0; | |
95 | ||
96 | do | |
97 | { | |
98 | // If we've seen this object already, bail out! | |
99 | // Otherwise, add it to the list | |
100 | if (ObjectExists(address)) | |
101 | return; | |
102 | ||
103 | object[numberOfObjects++] = address; | |
104 | ||
105 | // Get the object & decode its type, link address | |
106 | uint32_t hi = JaguarReadLong(address + 0, OP); | |
107 | uint32_t lo = JaguarReadLong(address + 4, OP); | |
108 | objectType = lo & 0x07; | |
109 | uint32_t link = ((hi << 11) | (lo >> 21)) & 0x3FFFF8; | |
110 | ||
111 | if (objectType == 3) | |
112 | { | |
113 | // Branch if YPOS < 2047 (or YPOS > 0) can be treated as a GOTO, so | |
114 | // don't do any discovery in that case. Otherwise, have at it: | |
115 | if (((lo & 0xFFFF) != 0x7FFB) && ((lo & 0xFFFF) != 0x8003)) | |
116 | // Recursion needed to follow all links! This does depth-first | |
117 | // recursion on the not-taken objects | |
118 | DiscoverObjects(address + 8); | |
119 | } | |
120 | ||
121 | // Get the next object... | |
122 | address = link; | |
123 | } | |
124 | while (objectType != 4); | |
125 | } | |
126 | ||
127 | ||
128 | void OPBrowserWindow::DumpObjectList(QString & list) | |
129 | { | |
130 | const char * opType[8] = { | |
131 | "(BITMAP)", "(SCALED BITMAP)", "(GPU INT)", "(BRANCH)", | |
132 | "(STOP)", "???", "???", "???" | |
133 | }; | |
134 | const char * ccType[8] = { | |
135 | "==", "<", ">", "(opflag set)", | |
136 | "(second half line)", "?", "?", "?" | |
137 | }; | |
138 | char buf[512]; | |
139 | ||
140 | for(uint32_t i=0; i<numberOfObjects; i++) | |
141 | { | |
142 | uint32_t address = object[i]; | |
143 | ||
144 | uint32_t hi = JaguarReadLong(address + 0, OP); | |
145 | uint32_t lo = JaguarReadLong(address + 4, OP); | |
146 | uint8_t objectType = lo & 0x07; | |
147 | uint32_t link = ((hi << 11) | (lo >> 21)) & 0x3FFFF8; | |
148 | sprintf(buf, "<br>%06X: %08X %08X %s -> %06X", address, hi, lo, opType[objectType], link); | |
149 | list += QString(buf); | |
150 | ||
151 | if (objectType == 3) | |
152 | { | |
153 | uint16_t ypos = (lo >> 3) & 0x7FF; | |
154 | uint8_t cc = (lo >> 14) & 0x07; // Proper # of bits == 3 | |
155 | sprintf(buf, " YPOS %s %u", ccType[cc], ypos); | |
156 | list += QString(buf); | |
157 | } | |
158 | ||
159 | list += "<br>"; | |
160 | ||
161 | // Yes, the OP really determines bitmap/scaled bitmap address for the | |
162 | // following phrases this way...! | |
163 | if (objectType == 0) | |
164 | DumpFixedObject(list, OPLoadPhrase(address + 0), | |
165 | OPLoadPhrase(address | 0x08)); | |
166 | ||
167 | if (objectType == 1) | |
168 | DumpScaledObject(list, OPLoadPhrase(address + 0), | |
169 | OPLoadPhrase(address | 0x08), OPLoadPhrase(address | 0x10)); | |
170 | ||
171 | if (address == link) // Ruh roh... | |
172 | { | |
173 | // Runaway recursive link is bad! | |
174 | sprintf(buf, "***** SELF REFERENTIAL LINK *****<br>"); | |
175 | list += QString(buf); | |
176 | } | |
177 | } | |
178 | ||
179 | list += "<br>"; | |
180 | } | |
181 | ||
182 | ||
183 | void OPBrowserWindow::DumpScaledObject(QString & list, uint64_t p0, uint64_t p1, uint64_t p2) | |
184 | { | |
185 | char buf[512]; | |
186 | ||
187 | sprintf(buf, " %08X %08X<br>", (uint32_t)(p1 >> 32), (uint32_t)(p1 & 0xFFFFFFFF)); | |
188 | list += QString(buf); | |
189 | sprintf(buf, " %08X %08X<br>", (uint32_t)(p2 >> 32), (uint32_t)(p2 & 0xFFFFFFFF)); | |
190 | list += QString(buf); | |
191 | DumpBitmapCore(list, p0, p1); | |
192 | uint32_t hscale = p2 & 0xFF; | |
193 | uint32_t vscale = (p2 >> 8) & 0xFF; | |
194 | uint32_t remainder = (p2 >> 16) & 0xFF; | |
195 | sprintf(buf, " [hsc: %02X, vsc: %02X, rem: %02X]<br>", hscale, vscale, remainder); | |
196 | list += QString(buf); | |
197 | } | |
198 | ||
199 | ||
200 | void OPBrowserWindow::DumpFixedObject(QString & list, uint64_t p0, uint64_t p1) | |
201 | { | |
202 | char buf[512]; | |
203 | ||
204 | sprintf(buf, " %08X %08X<br>", (uint32_t)(p1 >> 32), (uint32_t)(p1 & 0xFFFFFFFF)); | |
205 | list += QString(buf); | |
206 | DumpBitmapCore(list, p0, p1); | |
207 | } | |
208 | ||
209 | ||
210 | void OPBrowserWindow::DumpBitmapCore(QString & list, uint64_t p0, uint64_t p1) | |
211 | { | |
212 | char buf[512]; | |
213 | uint8_t op_bitmap_bit_depth[8] = { 1, 2, 4, 8, 16, 24, 32, 0 }; | |
214 | ||
215 | uint32_t bdMultiplier[8] = { 64, 32, 16, 8, 4, 2, 1, 1 }; | |
216 | uint8_t bitdepth = (p1 >> 12) & 0x07; | |
217 | //WAS: int16 ypos = ((p0 >> 3) & 0x3FF); // ??? What if not interlaced (/2)? | |
218 | int16_t ypos = ((p0 >> 3) & 0x7FF); // ??? What if not interlaced (/2)? | |
219 | int32_t xpos = p1 & 0xFFF; | |
220 | xpos = (xpos & 0x800 ? xpos | 0xFFFFF000 : xpos); // Sign extend that mutha! | |
221 | uint32_t iwidth = ((p1 >> 28) & 0x3FF); | |
222 | uint32_t dwidth = ((p1 >> 18) & 0x3FF); // Unsigned! | |
223 | uint16_t height = ((p0 >> 14) & 0x3FF); | |
224 | uint32_t link = ((p0 >> 24) & 0x7FFFF) << 3; | |
225 | uint32_t ptr = ((p0 >> 43) & 0x1FFFFF) << 3; | |
226 | uint32_t firstPix = (p1 >> 49) & 0x3F; | |
227 | uint8_t flags = (p1 >> 45) & 0x0F; | |
228 | uint8_t idx = (p1 >> 38) & 0x7F; | |
229 | uint32_t pitch = (p1 >> 15) & 0x07; | |
230 | ||
231 | sprintf(buf, " [%u x %u @ (%i, %u) (iw:%u, dw:%u) (%u bpp), p:%06X fp:%02X, fl:%s%s%s%s, idx:%02X, pt:%02X]<br>", | |
232 | iwidth * bdMultiplier[bitdepth], | |
233 | height, xpos, ypos, iwidth, dwidth, op_bitmap_bit_depth[bitdepth], | |
234 | ptr, firstPix, (flags & OPFLAG_REFLECT ? "REFLECT " : ""), | |
235 | (flags & OPFLAG_RMW ? "RMW " : ""), (flags & OPFLAG_TRANS ? "TRANS " : ""), | |
236 | (flags & OPFLAG_RELEASE ? "RELEASE" : ""), idx, pitch); | |
237 | list += QString(buf); | |
238 | } | |
239 |