#include "stty_sane.h"
#include "z80/z80.h"
-#define DKONG 1
-#define INVADERS 0
+#define DKONG 0
+#define INVADERS 1
#define GALAXIAN 0
#define PACMAN 0
#define APPLE 0
#define INVADERS_WIDTH 224
#define INVADERS_HEIGHT 256
-#define PADDED_WIDTH INVADERS_WIDTH
-#define PADDED_HEIGHT INVADERS_HEIGHT
+// see background.png (dimensions divided by 3)
+#define PADDED_WIDTH 388
+#define PADDED_HEIGHT 286
+
+#define HORIZ_PAD ((PADDED_WIDTH - INVADERS_WIDTH) / 2)
+#define VERT_PAD ((PADDED_HEIGHT - INVADERS_HEIGHT) / 2)
#define WINDOW_X_SCALE 3
#define WINDOW_Y_SCALE 3
bool frame_half;
#endif
-#if APPLE
+#if INVADERS
+uint32_t palette[0x100]; // extracted from ihx with correct byte order
+#elif APPLE
// see palette.py
uint32_t palette[0x10] = {
0xff000000,
#define ROM_INVADERS_G_ADDR 0x800
#define ROM_INVADERS_F_ADDR 0x1000
#define ROM_INVADERS_E_ADDR 0x1800
-#define MEM_SIZE 0x4000
+#define ROM_BACKGROUND_PALETTE_ADDR 0x4000
+#define ROM_BACKGROUND_ADDR 0x4300
+#define MEM_SIZE 0xf8038
#elif GALAXIAN
#define ROM_GALMIDW_U_ADDR 0
#define ROM_GALMIDW_V_ADDR 0x800
}
#endif
+#if INVADERS
+ for (int i = 0; i < 0x100; ++i)
+ palette[i] =
+ (mem[2 + i * 3 + ROM_BACKGROUND_PALETTE_ADDR] * 2 / 3) |
+ ((mem[1 + i * 3 + ROM_BACKGROUND_PALETTE_ADDR] * 2 / 3) << 8) |
+ ((mem[i * 3 + ROM_BACKGROUND_PALETTE_ADDR] * 2 / 3) << 16) |
+ 0xff000000;
+#endif
+
// main loop
long nb_instructions = 0, nb_cycles = 0;
int update_count = 0;
}
#elif INVADERS
// send z80 a vertical refresh interrupt
- int j0, j1;
+ int j0, j1, j2, j3;
if (frame_half == false) {
z80_gen_int(&cpu, 0xcf); // rst 8
j0 = 0;
- j1 = 96;
+ j1 = (HORIZ_PAD + 96) * WINDOW_X_SCALE;
+ j2 = 0;
+ j3 = 96;
frame_half = true;
}
else {
z80_gen_int(&cpu, 0xd7); // rst 0x10
- j0 = 96;
- j1 = INVADERS_WIDTH;
+ j0 = (HORIZ_PAD + 96) * WINDOW_X_SCALE;
+ j1 = WINDOW_WIDTH;
+ j2 = 96;
+ j3 = INVADERS_WIDTH;
frame_half = false;
}
+ for (int i = 0; i < WINDOW_HEIGHT; ++i)
+ for (int j = j0; j < j1; ++j)
+ frame[i][j] = palette[
+ /*(i / 3) & 0xff*/ mem[i * WINDOW_WIDTH + j + ROM_BACKGROUND_ADDR]
+ ];
+
for (int i = 0; i < INVADERS_HEIGHT; ++i) {
- int y = i * WINDOW_Y_SCALE;
+ int y = (VERT_PAD + i) * WINDOW_Y_SCALE;
int i1 = i ^ 0xff;
- for (int j = j0; j < j1; ++j) {
- int x = j * WINDOW_X_SCALE;
- uint32_t rgb = -(
- (mem[(i1 >> 3) + (j << 5) + VIDEO_RAM] >> (i1 & 7)) & 1
- );
- if (i >= 32 && i < 64)
- rgb &= 0xffff0000; // red flying saucer area
- else if (
- i >= 184 &&
- (i < 240 || (j >= 25 && j < 136))
- )
- rgb &= 0xff00ff00; // green base and lives area
- for (int k = 0; k < WINDOW_Y_SCALE; ++k)
- for (int l = 0; l < WINDOW_X_SCALE; ++l)
- frame[y + k][x + l] = rgb;
- }
+ for (int j = j2; j < j3; ++j)
+ if ((mem[(i1 >> 3) + (j << 5) + VIDEO_RAM] >> (i1 & 7)) & 1) {
+ int x = (HORIZ_PAD + j) * WINDOW_X_SCALE;
+ uint32_t rgb = 0xffffffff;
+ if (i >= 32 && i < 64)
+ rgb = 0xffff00ff; // magenta flying saucer area
+ else if (
+ i >= 184 &&
+ (i < 240 || (j >= 25 && j < 136))
+ )
+ rgb = 0xff00ff00; // green base and lives area
+ for (int k = 0; k < WINDOW_Y_SCALE; ++k)
+ for (int l = 0; l < WINDOW_X_SCALE; ++l)
+ frame[y + k][x + l] = rgb;
+ }
}
#elif GALAXIAN
// send z80 a vertical refresh interrupt
ROM_INVADERS_G_ADDR=0x800
ROM_INVADERS_F_ADDR=0x1000
ROM_INVADERS_E_ADDR=0x1800
+ROM_BACKGROUND_PALETTE_ADDR=0x4000
+ROM_BACKGROUND_ADDR=0x4300
ROMS= \
all: invaders0.ihx
invaders.h.ihx \
invaders.g.ihx \
invaders.f.ihx \
-invaders.e.ihx
+invaders.e.ihx \
+background_palette.ihx \
+background.ihx
hexmerge.py -o $@ $^
invaders.h.ihx: ../orig/invaders/invaders.h
invaders.e.ihx: ../orig/invaders/invaders.e
${BIN2HEX} --offset=${ROM_INVADERS_E_ADDR} $< $@
+background_palette.ihx: background_palette.bin
+ ${BIN2HEX} --offset=${ROM_BACKGROUND_PALETTE_ADDR} $< $@
+
+background.ihx: background.bin
+ ${BIN2HEX} --offset=${ROM_BACKGROUND_ADDR} $< $@
+
+background.bin background_palette.bin: background.png
+ ./indexed_to_raw.py $< background.bin background_palette.bin
+
clean:
- rm -f *.ihx
+ rm -f *.bin *.ihx
--- /dev/null
+#!/usr/bin/env python3
+
+import PIL.Image
+import sys
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+if len(sys.argv) < 4:
+ print(f'usage: {sys.argv[0]:s} in.png out.bin palette_out.bin')
+ sys.exit(EXIT_FAILURE)
+in_png = sys.argv[1]
+out_bin = sys.argv[2]
+palette_out_bin = sys.argv[3]
+
+image_in_pil = PIL.Image.open(in_png)
+assert image_in_pil.mode == 'P'
+print('width', image_in_pil.width, 'height', image_in_pil.height)
+with open(out_bin, 'wb') as fout:
+ fout.write(image_in_pil.tobytes())
+with open(palette_out_bin, 'wb') as fout:
+ fout.write(image_in_pil.palette.tobytes())
--- /dev/null
+#!/usr/bin/env python3
+
+import PIL.Image
+import sys
+
+EXIT_SUCCESS = 0
+EXIT_FAILURE = 1
+
+if len(sys.argv) < 6:
+ print(f'usage: {sys.argv[0]:s} width height in.bin palette_in.bin out.png')
+ sys.exit(EXIT_FAILURE)
+width = int(sys.argv[1])
+height = int(sys.argv[2])
+in_bin = sys.argv[3]
+palette_in_bin = sys.argv[4]
+out_png = sys.argv[5]
+
+image_out_pil = PIL.Image.new('P', (width, height), None)
+with open(in_bin, 'rb') as fin:
+ image_out_pil.frombytes(fin.read(width * height))
+with open(palette_in_bin, 'rb') as fin:
+ image_out_pil.putpalette(list(fin.read(0x300)))
+image_out_pil.save(out_png)