First commit
[clinton/Virtual-Jaguar-Rx.git] / src / gui / debug / opbrowser.cpp
CommitLineData
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
23OPBrowserWindow::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
49void 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
70void 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
79bool 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
92void 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
128void 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 "==", "&lt;", "&gt;", "(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
183void OPBrowserWindow::DumpScaledObject(QString & list, uint64_t p0, uint64_t p1, uint64_t p2)
184{
185 char buf[512];
186
187 sprintf(buf, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%08X %08X<br>", (uint32_t)(p1 >> 32), (uint32_t)(p1 & 0xFFFFFFFF));
188 list += QString(buf);
189 sprintf(buf, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%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, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[hsc: %02X, vsc: %02X, rem: %02X]<br>", hscale, vscale, remainder);
196 list += QString(buf);
197}
198
199
200void OPBrowserWindow::DumpFixedObject(QString & list, uint64_t p0, uint64_t p1)
201{
202 char buf[512];
203
204 sprintf(buf, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;%08X %08X<br>", (uint32_t)(p1 >> 32), (uint32_t)(p1 & 0xFFFFFFFF));
205 list += QString(buf);
206 DumpBitmapCore(list, p0, p1);
207}
208
209
210void 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, "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[%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