~ubuntu-branches/ubuntu/quantal/openmsx-debugger/quantal

« back to all changes in this revision

Viewing changes to src/VramBitMappedView.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Joost Yervante Damad
  • Date: 2009-12-06 07:40:02 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20091206074002-kssfkg1d6xbp6w9e
Tags: 0.0.0.svn20091206-1
New svn snapshot (Closes: #559612)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "VramBitMappedView.h"
 
2
#include <QPainter>
 
3
#include <algorithm>
 
4
#include <cstdio>
 
5
 
 
6
/** Clips x to the range [LO,HI].
 
7
  * Slightly faster than    std::min(HI, std::max(LO, x))
 
8
  * especially when no clipping is required.
 
9
  */
 
10
template <int LO, int HI>
 
11
static inline int clip(int x)
 
12
{
 
13
        return unsigned(x - LO) <= unsigned(HI - LO) ? x : (x < HI ? LO : HI);
 
14
}
 
15
 
 
16
 
 
17
VramBitMappedView::VramBitMappedView(QWidget* parent)
 
18
        : QWidget(parent)
 
19
        , image(512, 512, QImage::Format_RGB32)
 
20
{
 
21
        lines = 212;
 
22
        screenMode = 5;
 
23
        borderColor = 0;
 
24
        pallet = NULL;
 
25
        vramBase = NULL;
 
26
        vramAddress = 0;
 
27
        for (int i = 0; i < 15; ++i) {
 
28
                msxpallet[i] = qRgb(80, 80, 80);
 
29
        }
 
30
        setZoom(1.0f);
 
31
 
 
32
        // mouse update events when mouse is moved over the image, Quibus likes this
 
33
        // better then my preferd click-on-the-image
 
34
        setMouseTracking(true);
 
35
}
 
36
 
 
37
void VramBitMappedView::setZoom(float zoom)
 
38
{
 
39
        zoomFactor = std::max(1.0f, zoom);
 
40
        setFixedSize(int(512 * zoomFactor), int(lines * 2 * zoomFactor));
 
41
        update();
 
42
}
 
43
 
 
44
void VramBitMappedView::decode()
 
45
{
 
46
        if (!vramBase) return;
 
47
 
 
48
        printf("\n"
 
49
               "screenMode: %i\n"
 
50
               "vram to start decoding: %i\n",
 
51
               screenMode, vramAddress);
 
52
        switch (screenMode) {
 
53
        case 12:
 
54
                decodeSCR12();
 
55
                break;
 
56
        case 11:
 
57
        case 10:
 
58
                decodeSCR10();
 
59
                break;
 
60
        case 8:
 
61
                decodeSCR8();
 
62
                break;
 
63
        case 7:
 
64
                decodeSCR7();
 
65
                break;
 
66
        case 6:
 
67
                decodeSCR6();
 
68
                break;
 
69
        case 5:
 
70
                decodeSCR5();
 
71
                break;
 
72
        }
 
73
        piximage = piximage.fromImage(image);
 
74
        update();
 
75
}
 
76
 
 
77
void VramBitMappedView::decodePallet()
 
78
{
 
79
        if (!pallet) return;
 
80
 
 
81
        for (int i = 0; i < 16; ++i) {
 
82
                int r = (pallet[2 * i + 0] & 0xf0) >> 4;
 
83
                int b = (pallet[2 * i + 0] & 0x0f);
 
84
                int g = (pallet[2 * i + 1] & 0x0f);
 
85
 
 
86
                r = (r >> 1) | (r << 2) | (r << 5);
 
87
                b = (b >> 1) | (b << 2) | (b << 5);
 
88
                g = (g >> 1) | (g << 2) | (g << 5);
 
89
 
 
90
                msxpallet[i] = qRgb(r, g, b);
 
91
        }
 
92
}
 
93
 
 
94
static unsigned interleave(unsigned x)
 
95
{
 
96
        return (x >> 1) | ((x & 1) << 16);
 
97
}
 
98
 
 
99
void VramBitMappedView::setPixel2x2(int x, int y, QRgb c)
 
100
{
 
101
        image.setPixel(2 * x + 0, 2 * y + 0, c);
 
102
        image.setPixel(2 * x + 1, 2 * y + 0, c);
 
103
        image.setPixel(2 * x + 0, 2 * y + 1, c);
 
104
        image.setPixel(2 * x + 1, 2 * y + 1, c);
 
105
}
 
106
void VramBitMappedView::setPixel1x2(int x, int y, QRgb c)
 
107
{
 
108
        image.setPixel(x, 2 * y + 0, c);
 
109
        image.setPixel(x, 2 * y + 1, c);
 
110
}
 
111
 
 
112
void VramBitMappedView::decodeSCR12()
 
113
{
 
114
        int offset = vramAddress;
 
115
        for (int y = 0; y < lines; ++y) {
 
116
                for (int x = 0; x < 256; x += 4) {
 
117
                        unsigned p[4];
 
118
                        p[0] = vramBase[interleave(offset++)];
 
119
                        p[1] = vramBase[interleave(offset++)];
 
120
                        p[2] = vramBase[interleave(offset++)];
 
121
                        p[3] = vramBase[interleave(offset++)];
 
122
                        int j = (p[2] & 7) + ((p[3] & 3) << 3) - ((p[3] & 4) << 3);
 
123
                        int k = (p[0] & 7) + ((p[1] & 3) << 3) - ((p[1] & 4) << 3);
 
124
 
 
125
                        for (unsigned n = 0; n < 4; ++n) {
 
126
                                int z = p[n] >> 3;
 
127
                                int r = clip<0, 31>(z + j);
 
128
                                int g = clip<0, 31>(z + k);
 
129
                                int b = clip<0, 31>((5 * z - 2 * j - k) / 4);
 
130
                                r = (r << 3) | (r >> 2);
 
131
                                b = (b << 3) | (b >> 2);
 
132
                                g = (g << 3) | (g >> 2);
 
133
                                setPixel2x2(x + n, y, qRgb(r, g, b));
 
134
                        }
 
135
                }
 
136
        }
 
137
}
 
138
 
 
139
void VramBitMappedView::decodeSCR10()
 
140
{
 
141
        int offset = vramAddress;
 
142
        for (int y = 0; y < lines; ++y) {
 
143
                for (int x = 0; x < 256; x += 4) {
 
144
                        unsigned p[4];
 
145
                        p[0] = vramBase[interleave(offset++)];
 
146
                        p[1] = vramBase[interleave(offset++)];
 
147
                        p[2] = vramBase[interleave(offset++)];
 
148
                        p[3] = vramBase[interleave(offset++)];
 
149
                        int j = (p[2] & 7) + ((p[3] & 3) << 3) - ((p[3] & 4) << 3);
 
150
                        int k = (p[0] & 7) + ((p[1] & 3) << 3) - ((p[1] & 4) << 3);
 
151
 
 
152
                        for (unsigned n = 0; n < 4; ++n) {
 
153
                                QRgb c;
 
154
                                if (p[n] & 0x08) {
 
155
                                        // YAE
 
156
                                        c = msxpallet[p[n] >> 4];
 
157
                                } else {
 
158
                                        // YJK
 
159
                                        int z = p[n] >> 3;
 
160
                                        int r = clip<0, 31>(z + j);
 
161
                                        int g = clip<0, 31>(z + k);
 
162
                                        int b = clip<0, 31>((5 * z - 2 * j - k) / 4);
 
163
                                        r = (r << 3) | (r >> 2);
 
164
                                        b = (b << 3) | (b >> 2);
 
165
                                        g = (g << 3) | (g >> 2);
 
166
                                        c = qRgb(r, g, b);
 
167
                                }
 
168
                                setPixel2x2(x + n, y, c);
 
169
                        }
 
170
                }
 
171
        }
 
172
}
 
173
 
 
174
void VramBitMappedView::decodeSCR8()
 
175
{
 
176
        int offset = vramAddress;
 
177
        for (int y = 0; y < lines; ++y) {
 
178
                for (int x = 0; x < 256; ++x) {
 
179
                        unsigned char val = vramBase[interleave(offset++)];
 
180
                        int b = val & 0x03;
 
181
                        int r = val & 0x1C;
 
182
                        int g = val & 0xE0;
 
183
 
 
184
                        b = b | (b << 2) | (b << 4) | (b << 6);
 
185
                        r = (r >> 2) | r | (r << 3);
 
186
                        g = g | (g >> 3) | (g >> 6);
 
187
 
 
188
                        setPixel2x2(x, y, qRgb(r, g, b));
 
189
                }
 
190
        }
 
191
}
 
192
 
 
193
QRgb VramBitMappedView::getColor(int c)
 
194
{
 
195
        // TODO do we need to look at the TP bit???
 
196
        return msxpallet[c ? c : borderColor];
 
197
}
 
198
 
 
199
void VramBitMappedView::decodeSCR7()
 
200
{
 
201
        int offset = vramAddress;
 
202
        for (int y = 0; y < lines; ++y) {
 
203
                for (int x = 0; x < 512; x += 2) {
 
204
                        int val = vramBase[interleave(offset++)];
 
205
                        setPixel1x2(x + 0, y, getColor((val >> 4) & 15));
 
206
                        setPixel1x2(x + 1, y, getColor((val >> 0) & 15));
 
207
                }
 
208
        }
 
209
}
 
210
 
 
211
void VramBitMappedView::decodeSCR6()
 
212
{
 
213
        int offset = vramAddress;
 
214
        for (int y = 0; y < lines; ++y) {
 
215
                for (int x = 0; x < 512; x += 4) {
 
216
                        int val = vramBase[offset++];
 
217
                        setPixel1x2(x + 0, y, getColor((val >> 6) & 3));
 
218
                        setPixel1x2(x + 1, y, getColor((val >> 4) & 3));
 
219
                        setPixel1x2(x + 2, y, getColor((val >> 2) & 3));
 
220
                        setPixel1x2(x + 3, y, getColor((val >> 0) & 3));
 
221
                }
 
222
        }
 
223
}
 
224
 
 
225
void VramBitMappedView::decodeSCR5()
 
226
{
 
227
        int offset = vramAddress;
 
228
        for (int y = 0; y < lines; ++y) {
 
229
                for (int x = 0; x < 256; x += 2) {
 
230
                        int val = vramBase[offset++];
 
231
                        setPixel2x2(x + 0, y, getColor((val >> 4) & 15));
 
232
                        setPixel2x2(x + 1, y, getColor((val >> 0) & 15));
 
233
                }
 
234
        }
 
235
}
 
236
 
 
237
void VramBitMappedView::paintEvent(QPaintEvent* event)
 
238
{
 
239
        QRect srcRect(0, 0, 512, 2 * lines);
 
240
        QRect dstRect(0, 0, int(512 * zoomFactor), int(2 * lines * zoomFactor));
 
241
        QPainter qp(this);
 
242
        //qp.drawImage(rect(),image,srcRect);
 
243
        qp.drawPixmap(dstRect, piximage, srcRect);
 
244
}
 
245
 
 
246
void VramBitMappedView::refresh()
 
247
{
 
248
        decodePallet();
 
249
        decode();
 
250
        update();
 
251
}
 
252
 
 
253
void VramBitMappedView::mouseMoveEvent(QMouseEvent* e)
 
254
{
 
255
        static const unsigned bytes_per_line[] = {
 
256
                0,      //screen 0
 
257
                1,      //screen 1
 
258
                2,      // 2
 
259
                3,      // 3
 
260
                4,
 
261
                128,    // 5
 
262
                128,
 
263
                256,    // 7
 
264
                256,
 
265
                256,    // 9
 
266
                256,
 
267
                256,
 
268
                256
 
269
        };
 
270
        static const unsigned pixels_per_byte[] = {
 
271
                0,1,2,3,4,
 
272
                2,      // 5
 
273
                4,
 
274
                2,      // 7
 
275
                1,
 
276
                1,      //9
 
277
                1,
 
278
                1,
 
279
                1
 
280
        };
 
281
 
 
282
        int x = int(e->x() / zoomFactor);
 
283
        int y = int(e->y() / zoomFactor) / 2;
 
284
 
 
285
        // I see negative y-coords sometimes, so for safety clip the coords
 
286
        x = std::max(0, std::min(511, x));
 
287
        y = std::max(0, std::min(255, y));
 
288
 
 
289
        if ((screenMode != 6) && (screenMode != 7)) {
 
290
                x /= 2;
 
291
        }
 
292
 
 
293
        unsigned offset = bytes_per_line[screenMode] * y
 
294
                        + x / pixels_per_byte[screenMode];
 
295
        unsigned addr = offset + vramAddress;
 
296
        int val = (screenMode >= 7) ? vramBase[interleave(addr)]
 
297
                                    : vramBase[addr];
 
298
 
 
299
        int color;
 
300
        switch (screenMode) {
 
301
                case 5:
 
302
                case 7:
 
303
                        color = ((x & 1) ? val : (val >> 4)) & 15;
 
304
                        break;
 
305
                case 6:
 
306
                        color = (val >> (2 * (3 - (x & 3)))) & 3;
 
307
                        break;
 
308
                case 8:
 
309
                case 10:
 
310
                case 11:
 
311
                case 12:
 
312
                        color = val;
 
313
                        break;
 
314
                default:
 
315
                        color = 0; // avoid warning
 
316
        }
 
317
        emit imagePosition(x, y, color, addr, val);
 
318
}
 
319
 
 
320
void VramBitMappedView::mousePressEvent(QMouseEvent* e)
 
321
{
 
322
        // since mouseMove only emits the correct signal we reuse/abuse that method
 
323
        mouseMoveEvent(e);
 
324
 
 
325
        decodePallet();
 
326
        decode();
 
327
        update();
 
328
}
 
329
 
 
330
void VramBitMappedView::setBorderColor(int value)
 
331
{
 
332
        borderColor = clip<0, 15>(value);
 
333
        decodePallet();
 
334
        decode();
 
335
        update();
 
336
}
 
337
 
 
338
void VramBitMappedView::setScreenMode(int mode)
 
339
{
 
340
        screenMode = mode;
 
341
        decode();
 
342
        update();
 
343
}
 
344
 
 
345
void VramBitMappedView::setLines(int nrLines)
 
346
{
 
347
        lines = nrLines;
 
348
        decode();
 
349
        setFixedSize(int(512 * zoomFactor), int(lines * 2 * zoomFactor));
 
350
        update();
 
351
        //setZoom(zoomFactor);
 
352
}
 
353
 
 
354
void VramBitMappedView::setVramAddress(int adr)
 
355
{
 
356
        vramAddress = adr;
 
357
        decodePallet();
 
358
        decode();
 
359
        update();
 
360
}
 
361
 
 
362
void VramBitMappedView::setVramSource(const unsigned char* adr)
 
363
{
 
364
        vramBase = adr;
 
365
        decodePallet();
 
366
        decode();
 
367
        update();
 
368
}
 
369
 
 
370
void VramBitMappedView::setPaletteSource(const unsigned char* adr)
 
371
{
 
372
        pallet = adr;
 
373
        decodePallet();
 
374
        decode();
 
375
        update();
 
376
}