// includes cool down sequence
#define PADDED_WIDTH (APPLE_WIDTH + 3)
#define PADDED_HEIGHT APPLE_HEIGHT
-#define PADDED_WORDS ((PADDED_WIDTH + 31) >> 5)
+// note: extra 2 pixels for unfringe
+#define PADDED_WORDS ((PADDED_WIDTH + 33) >> 5)
#define WINDOW_X_SCALE 2
#define WINDOW_Y_SCALE 4
// can make this green or amber to be more realistic
uint32_t mono_palette[2] = {0xff000000, 0xffffffff};
+// see unfringe.py
+uint8_t decode[0x80] = {
+ 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x66, 0x00,
+ 0x08, 0x08, 0x2a, 0x08, 0x4c, 0x4c, 0x6e, 0x7f,
+ 0x11, 0x11, 0x11, 0x33, 0x55, 0x55, 0x66, 0x77,
+ 0x19, 0x19, 0x19, 0x19, 0x5d, 0x5d, 0x7f, 0x7f,
+ 0x00, 0x22, 0x22, 0x22, 0x44, 0x55, 0x66, 0x66,
+ 0x2a, 0x2a, 0x2a, 0x2a, 0x4c, 0x2a, 0x6e, 0x6e,
+ 0x33, 0x33, 0x33, 0x33, 0x33, 0x55, 0x77, 0x77,
+ 0x3b, 0x19, 0x3b, 0x3b, 0x7f, 0x5d, 0x7f, 0x7f,
+ 0x00, 0x00, 0x22, 0x00, 0x44, 0x44, 0x66, 0x44,
+ 0x08, 0x08, 0x2a, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
+ 0x11, 0x11, 0x55, 0x33, 0x55, 0x55, 0x55, 0x55,
+ 0x19, 0x19, 0x2a, 0x3b, 0x5d, 0x5d, 0x5d, 0x7f,
+ 0x00, 0x00, 0x22, 0x22, 0x66, 0x66, 0x66, 0x66,
+ 0x08, 0x19, 0x2a, 0x2a, 0x4c, 0x6e, 0x6e, 0x6e,
+ 0x00, 0x11, 0x33, 0x33, 0x77, 0x55, 0x77, 0x77,
+ 0x7f, 0x19, 0x3b, 0x3b, 0x7f, 0x7f, 0x7f, 0x7f,
+};
+
struct cpu_65c02 cpu;
bool jam_flag;
int main(int argc, char **argv) {
int argn = 1;
+ bool unfringe = false;
char *cg_rom_file = NULL;
char *video_rom_file = NULL;
#if APPLE_IIE
#endif
while (argn < argc) {
if (strcmp(argv[argn], "--help") == 0) {
- printf("usage: %s [--cg-rom=file.bin] [--video-rom=file.bin] [--NN-rom=file.bin ...] [program.obj[,aNNNN] ...] [-- child-executable [child-argument ...]]\n", argv[0]);
+ printf("usage: %s [--unfringe] [--cg-rom=file.bin] [--video-rom=file.bin] [--NN-rom=file.bin ...] [program.obj[,aNNNN] ...] [-- child-executable [child-argument ...]]\n", argv[0]);
exit(EXIT_FAILURE);
}
- if (memcmp(argv[argn], "--cg-rom=", 9) == 0)
+ if (strcmp(argv[argn], "--unfringe") == 0)
+ unfringe = true;
+ else if (memcmp(argv[argn], "--cg-rom=", 9) == 0)
cg_rom_file = argv[argn] + 9;
else if (memcmp(argv[argn], "--video_rom=", 12) == 0)
video_rom_file = argv[argn] + 12;
}
}
}
+ else if (unfringe) {
+ // hires or gr (colour burst), interpreted
+ int k = (buf[0] & 3) << 5, x = 0, y = i * WINDOW_Y_SCALE;
+ for (int j = 2; j < PADDED_WIDTH + 2; ++j) {
+ k = (k >> 1) | (((buf[j >> 5] >> (j & 0x1f)) & 1) << 6);
+ uint32_t v = palette[(decode[k] >> ((2 - j) & 3)) & 0xf];
+ for (int l = 0; l < WINDOW_X_SCALE; ++l) {
+ for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+ frame[y + m][x] = v;
+ ++x;
+ }
+ }
+ }
else {
// hires or gr (colour burst)
int k = 0, x = 0, y = i * WINDOW_Y_SCALE;
--- /dev/null
+#!/usr/bin/env python3
+
+# create a lookup table to decode Apple (NTSC) video without fringes
+
+import sys
+
+# decoder uses a majority voting scheme with tie breaking by parity
+def parity(nibble):
+ nibble = (nibble & 3) ^ (nibble >> 2)
+ nibble = (nibble & 1) ^ (nibble >> 1)
+ return nibble
+
+decode = []
+for i in range(0x80):
+ candidates = [
+ i & 0xf,
+ (i & 0xe) | ((i >> 4) & 1),
+ (i & 0xc) | ((i >> 4) & 3),
+ (i & 8) | ((i >> 4) & 7)
+ ]
+ if candidates[1] == candidates[2]:
+ result = candidates[1]
+ elif candidates[0] == candidates[1] and candidates[2] != candidates[3]:
+ result = candidates[0]
+ elif candidates[0] != candidates[1] and candidates[2] == candidates[3]:
+ result = candidates[3]
+ elif 0 in candidates:
+ result = 0
+ elif 0xf in candidates:
+ result = 0xf
+ else:
+ # we assume it is a fringed transition from candidate 0 to candidate 3
+ # on the left are more of candidate 0, on the right are more of candidate 3
+ # so to ensure a clean transition, we just have to choose candidate 0 or 3
+ p0 = parity(candidates[0])
+ p3 = parity(candidates[3])
+ if p0 < p3:
+ result = candidates[0]
+ elif p3 < p0:
+ result = candidates[3]
+ else:
+ assert False
+ # actual colour indicated by "result" should be rotated left by (x + n) % 4,
+ # as we don't have a circular rotate, repeat the lower 3 bits for right shift
+ decode.append(result | ((result & 7) << 4))
+
+sys.stdout.write(
+ '''uint8_t decode[0x80] = {{
+{0:s}}};
+'''.format(
+ ''.join(
+ [
+ ' ' + ' '.join([f'0x{j:02x},' for j in decode[i:i + 8]]) + '\n'
+ for i in range(0, 0x80, 8)
+ ]
+ )
+ )
+)