1
#include "VramBitMappedView.h"
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.
10
template <int LO, int HI>
11
static inline int clip(int x)
13
return unsigned(x - LO) <= unsigned(HI - LO) ? x : (x < HI ? LO : HI);
17
VramBitMappedView::VramBitMappedView(QWidget* parent)
19
, image(512, 512, QImage::Format_RGB32)
27
for (int i = 0; i < 15; ++i) {
28
msxpallet[i] = qRgb(80, 80, 80);
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);
37
void VramBitMappedView::setZoom(float zoom)
39
zoomFactor = std::max(1.0f, zoom);
40
setFixedSize(int(512 * zoomFactor), int(lines * 2 * zoomFactor));
44
void VramBitMappedView::decode()
46
if (!vramBase) return;
50
"vram to start decoding: %i\n",
51
screenMode, vramAddress);
73
piximage = piximage.fromImage(image);
77
void VramBitMappedView::decodePallet()
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);
86
r = (r >> 1) | (r << 2) | (r << 5);
87
b = (b >> 1) | (b << 2) | (b << 5);
88
g = (g >> 1) | (g << 2) | (g << 5);
90
msxpallet[i] = qRgb(r, g, b);
94
static unsigned interleave(unsigned x)
96
return (x >> 1) | ((x & 1) << 16);
99
void VramBitMappedView::setPixel2x2(int x, int y, QRgb c)
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);
106
void VramBitMappedView::setPixel1x2(int x, int y, QRgb c)
108
image.setPixel(x, 2 * y + 0, c);
109
image.setPixel(x, 2 * y + 1, c);
112
void VramBitMappedView::decodeSCR12()
114
int offset = vramAddress;
115
for (int y = 0; y < lines; ++y) {
116
for (int x = 0; x < 256; x += 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);
125
for (unsigned n = 0; n < 4; ++n) {
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));
139
void VramBitMappedView::decodeSCR10()
141
int offset = vramAddress;
142
for (int y = 0; y < lines; ++y) {
143
for (int x = 0; x < 256; x += 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);
152
for (unsigned n = 0; n < 4; ++n) {
156
c = msxpallet[p[n] >> 4];
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);
168
setPixel2x2(x + n, y, c);
174
void VramBitMappedView::decodeSCR8()
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++)];
184
b = b | (b << 2) | (b << 4) | (b << 6);
185
r = (r >> 2) | r | (r << 3);
186
g = g | (g >> 3) | (g >> 6);
188
setPixel2x2(x, y, qRgb(r, g, b));
193
QRgb VramBitMappedView::getColor(int c)
195
// TODO do we need to look at the TP bit???
196
return msxpallet[c ? c : borderColor];
199
void VramBitMappedView::decodeSCR7()
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));
211
void VramBitMappedView::decodeSCR6()
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));
225
void VramBitMappedView::decodeSCR5()
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));
237
void VramBitMappedView::paintEvent(QPaintEvent* event)
239
QRect srcRect(0, 0, 512, 2 * lines);
240
QRect dstRect(0, 0, int(512 * zoomFactor), int(2 * lines * zoomFactor));
242
//qp.drawImage(rect(),image,srcRect);
243
qp.drawPixmap(dstRect, piximage, srcRect);
246
void VramBitMappedView::refresh()
253
void VramBitMappedView::mouseMoveEvent(QMouseEvent* e)
255
static const unsigned bytes_per_line[] = {
270
static const unsigned pixels_per_byte[] = {
282
int x = int(e->x() / zoomFactor);
283
int y = int(e->y() / zoomFactor) / 2;
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));
289
if ((screenMode != 6) && (screenMode != 7)) {
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)]
300
switch (screenMode) {
303
color = ((x & 1) ? val : (val >> 4)) & 15;
306
color = (val >> (2 * (3 - (x & 3)))) & 3;
315
color = 0; // avoid warning
317
emit imagePosition(x, y, color, addr, val);
320
void VramBitMappedView::mousePressEvent(QMouseEvent* e)
322
// since mouseMove only emits the correct signal we reuse/abuse that method
330
void VramBitMappedView::setBorderColor(int value)
332
borderColor = clip<0, 15>(value);
338
void VramBitMappedView::setScreenMode(int mode)
345
void VramBitMappedView::setLines(int nrLines)
349
setFixedSize(int(512 * zoomFactor), int(lines * 2 * zoomFactor));
351
//setZoom(zoomFactor);
354
void VramBitMappedView::setVramAddress(int adr)
362
void VramBitMappedView::setVramSource(const unsigned char* adr)
370
void VramBitMappedView::setPaletteSource(const unsigned char* adr)