#define APPLE_HEIGHT 192
#define APPLE_HIRES0 0x2000
+// includes cool down sequence
+#define PADDED_WIDTH (APPLE_WIDTH + 3)
+#define PADDED_HEIGHT APPLE_HEIGHT
+#define PADDED_WORDS ((PADDED_WIDTH + 31) >> 5)
+
#define WINDOW_X_SCALE 2
#define WINDOW_Y_SCALE 4
-#define WINDOW_WIDTH (APPLE_WIDTH * WINDOW_X_SCALE)
-#define WINDOW_HEIGHT (APPLE_HEIGHT * WINDOW_Y_SCALE)
+#define WINDOW_WIDTH (PADDED_WIDTH * WINDOW_X_SCALE)
+#define WINDOW_HEIGHT (PADDED_HEIGHT * WINDOW_Y_SCALE)
#define INSTRS_PER_UPDATE 1500
SDL_Surface *surface;
uint32_t frame[WINDOW_HEIGHT][WINDOW_WIDTH];
-// linear 0.250000 -> gamma encoded 0.537099 -> 0x89
-// linear 0.500000 -> gamma encoded 0.735357 -> 0xbc
-// linear 0.750000 -> gamma encoded 0.880825 -> 0xe1
-uint32_t argb[WINDOW_X_SCALE * 4] = {
- // hue R G B
- 0xffff8900, // 15 1.00 0.25 0.00
- //0xffff0000, // 0 1.00 0.00 0.00
- //0xffff0089, // 345 1.00 0.00 0.25
- 0xffff00bc, // 330 1.00 0.00 0.50
- //0xffff00e1, // 315 1.00 0.00 0.75
- //0xffff00ff, // 300 1.00 0.00 1.00
- 0xffe100ff, // 285 0.75 0.00 1.00
- //0xffbc00ff, // 270 0.50 0.00 1.00
- //0xff8900ff, // 255 0.25 0.00 1.00
- 0xff0000ff, // 289 0.00 0.00 1.00
- //0xff0089ff, // 225 0.00 0.25 1.00
- //0xff00bcff, // 210 0.00 0.50 1.00
- 0xff00e1ff, // 195 0.00 0.75 1.00
- //0xff00ffff, // 1bc 0.00 1.00 1.00
- //0xff00ffe1, // 165 0.00 1.00 0.75
- 0xff00ffbc, // 150 0.00 1.00 0.50
- //0xff00ff89, // 135 0.00 1.00 0.25
- //0xff00ff00, // 120 0.00 1.00 0.00
- 0xff89ff00, // 105 0.25 1.00 0.00
- //0xffbcff00, // 90 0.50 1.00 0.00
- //0xffe1ff00, // 75 0.75 1.00 0.00
- 0xffffff00, // 60 1.00 1.00 0.00
- //0xffffe100, // 45 1.00 0.75 0.00
- //0xffffbc00, // 30 1.00 0.50 0.00
+// see palette.py
+uint32_t palette[0x10] = {
+ 0xff000000,
+ 0xffbc0089,
+ 0xff0000bc,
+ 0xffbc00e1,
+ 0xff00bc89,
+ 0xffbcbcbc,
+ 0xff00bce1,
+ 0xffbcbcff,
+ 0xffbcbc00,
+ 0xffffbc89,
+ 0xffbcbcbc,
+ 0xffffbce1,
+ 0xffbcff89,
+ 0xffffffbc,
+ 0xffbcffe1,
+ 0xffffffff,
};
VrEmu6502 *cpu;
// draw
memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
for (int i = 0; i < APPLE_HEIGHT; ++i) {
- int y = i * WINDOW_Y_SCALE;
int line =
APPLE_HIRES0 |
(i >> 6) * 40 |
((i & 0x38) << 4) |
((i & 7) << 10);
+ uint32_t buf[PADDED_WORDS];
+ memset(buf, 0, PADDED_WORDS * sizeof(uint32_t));
for (int j = 0; j < 40; ++j) {
int data = mem[line + j];
int hibit = data >> 7;
for (int k = 0; k < 7; ++k) {
if (data & 1) {
- int x = (((j * 7 + k) << 1) + hibit) * WINDOW_X_SCALE;
- for (int l = 0; l < WINDOW_X_SCALE * 2; ++l) {
- uint32_t v = argb[x & (WINDOW_X_SCALE * 4 - 1)];
- for (int m = 0; m < WINDOW_Y_SCALE; ++m)
- frame[y + m][x] = v;
- ++x;
- }
+ int l = ((j * 7 + k) << 1) + hibit;
+ buf[l >> 5] |= 1 << (l & 0x1f);
+ ++l;
+ buf[l >> 5] |= 1 << (l & 0x1f);
}
data >>= 1;
}
}
+ int k = 0, x = 0, y = i * WINDOW_Y_SCALE;
+ for (int j = 0; j < PADDED_WIDTH; ++j) {
+ int mask = 1 << (j & 3);
+ k = (k & ~mask) | ((buf[j >> 5] >> (j & 0x1c)) & mask);
+ uint32_t v = palette[k];
+ for (int l = 0; l < WINDOW_X_SCALE; ++l) {
+ for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+ frame[y + m][x] = v;
+ ++x;
+ }
+ }
}
SDL_UpdateTexture(texture, NULL, frame, WINDOW_WIDTH * sizeof(uint32_t));
SDL_RenderCopy(renderer, texture, NULL, NULL);
--- /dev/null
+#!/usr/bin/env python3
+
+import math
+import numpy
+import sys
+
+hues = numpy.array(
+ [
+ [1., 1., 0., 0., 0., 1., 1.],
+ [0., 1., 1., 1., 0., 0., 0.],
+ [0., 0., 0., 1., 1., 1., 0.],
+ ],
+ numpy.double
+)
+
+
+hue = 330.
+primaries = []
+for i in range(4):
+ j = hue / 60.
+ k = math.floor(j)
+ j -= k
+ primaries.append(hues[:, k] + j * (hues[:, k + 1] - hues[:, k]))
+ hue = (hue - 90.) % 360.
+primaries = numpy.stack(primaries, 1)
+
+palette = []
+for i in range(0x10):
+ bits = (i >> numpy.arange(4, dtype = numpy.int32) & 1).astype(bool)
+ palette.append(primaries @ bits)
+palette = numpy.stack(palette, 1)
+palette /= numpy.max(palette)
+#print('linear', palette.transpose())
+
+# SRGB gamma encode
+mask = palette < .0031308
+palette[mask] *= 12.92
+palette[~mask] = (1.055 * palette[~mask] ** (1. / 2.4)) - .055
+#print('encoded', palette.transpose())
+
+palette = numpy.sum(
+ numpy.round(palette * 255.).astype(numpy.int32) <<
+ numpy.arange(16, -8, -8, numpy.int32)[:, numpy.newaxis],
+ 0
+) + 0xff000000
+sys.stdout.write(
+ '''uint32_t palette[0x10] = {{
+{0:s}}};
+'''.format(
+ ''.join([f' 0x{palette[i]:08x},\n' for i in range(0x10)])
+ )
+)