#define WINDOW_WIDTH (PADDED_WIDTH * WINDOW_X_SCALE)
#define WINDOW_HEIGHT (PADDED_HEIGHT * WINDOW_Y_SCALE)
-#define CYCLES_PER_SAMPLE 34 // 44100 Hz @ 1.5 MHz
-#define SAMPLES_PER_UPDATE 500
+#define CYCLES_PER_SAMPLE 68 // 44100 Hz @ 3 MHz
+#define SAMPLES_PER_UPDATE 735 // 60 Hz @ 44100 Hz
#if GALAXIAN
#define RAM_START 0x4000
#define IO_PAGE 0x6000
#define HW_INT_ENABLE 0x6031 // z80 7001
+#define HW_STARS_ENABLE 0x6034 // z80 7004
#elif PACMAN
#define INT_VECTOR 0
if (mem[HW_INT_ENABLE] & 1)
cpu.nmi_pending = true;
+ // draw stars
+ if (mem[HW_STARS_ENABLE] & 1) {
+ static uint32_t lfsr0 = 0xffffffffU;
+ static int blink_state = 0;
+ static const uint32_t blink_table[4] =
+ {0x4000, 0x1000, 0x7e00, 0x7e00};
+
+ // stars are drawn when (lfsr & 0x1ff) == 1
+ // the colour comes from (lfsr >> 9) & 0x3f
+ // but just for fun we implement our own LFSR
+ // stars are suppressed at certain times, based on
+ // the blink state and certain of the colour bits
+ uint32_t lfsr = lfsr0;
+ for (int i = 0; i < GALAXIAN_WIDTH; ++i) {
+ int x = i * WINDOW_X_SCALE;
+ for (int j = GALAXIAN_HEIGHT * 2 - 1; j >= 0; --j) {
+ int y0 = (j * WINDOW_Y_SCALE) >> 1;
+ int y1 = ((j + 1) * WINDOW_Y_SCALE) >> 1;
+ uint32_t rgb = 0xff000000;
+ if (
+ (lfsr & 0x1ff) == 1 &&
+ ((i ^ (j >> 3)) & 1) &&
+ ((blink_state & 0x300) != 0x200 || (i & 2) != 0) &&
+ (lfsr & blink_table[blink_state >> 8])
+ )
+ rgb =
+ ((((lfsr & 0x600) * 0x55) & 0x1fc00) << 6) |
+ ((((lfsr & 0x1800) * 0x55) & 0x7f000) >> 4) |
+ ((((lfsr & 0x6000) * 0x55) & 0x1fc000) >> 14) |
+ 0xff808080;
+ for (int k = y0; k < y1; ++k)
+ for (int l = 0; l < WINDOW_X_SCALE; ++l)
+ frame[k][x + l] = rgb;
+ lfsr = (lfsr >> 1) ^ ((lfsr & 1) * 0xedb88320U);
+ }
+ }
+
+ lfsr0 = (lfsr0 >> 1) ^ ((lfsr0 & 1) * 0xedb88320U);
+ blink_state = (blink_state + 11) & 0x3ff;
+ }
+ else
+ memset(frame, 0, WINDOW_HEIGHT * WINDOW_WIDTH * sizeof(uint32_t));
+
// draw tiles
for (int i = 0; i < 32; ++i) {
int scroll = mem[(i << 1) | SPRITE_RAM] + 0x10;
if (x1 >= 0 && x1 < GALAXIAN_WIDTH) {
int data0 = mem[l ^ tile_base0] << (k & 7);
int data1 = mem[l ^ tile_base1] << (k & 7);
- int colour = mem[
- ((data0 & 0x80) >> 7) |
- ((data1 & 0x80) >> 6) |
- palette_base
- ]; // approximately bbgggrrr
- uint32_t rgb =
- ((((colour & 7) * 0x49) & 0x1fe) << 15) |
- ((((colour & 0x38) * 0x49) & 0xff0) << 4) |
- ((((colour & 0xc0) * 0x55) & 0x3fc0) >> 6) |
- 0xff000000;
- x1 *= WINDOW_X_SCALE;
- for (int m = 0; m < WINDOW_Y_SCALE; ++m)
- for (int n = 0; n < WINDOW_X_SCALE; ++n)
- frame[y1 + m][x1 + n] = rgb;
+ if ((data0 | data1) & 0x80) {
+ int colour = mem[
+ ((data0 & 0x80) >> 7) |
+ ((data1 & 0x80) >> 6) |
+ palette_base
+ ]; // approximately bbgggrrr
+ uint32_t rgb =
+ ((((colour & 7) * 0x49) & 0x1fe) << 15) |
+ ((((colour & 0x38) * 0x49) & 0xff0) << 4) |
+ (((colour & 0xc0) * 0x55) >> 6) | // 0x3fc0 >> 6
+ 0xff000000;
+ x1 *= WINDOW_X_SCALE;
+ for (int m = 0; m < WINDOW_Y_SCALE; ++m)
+ for (int n = 0; n < WINDOW_X_SCALE; ++n)
+ frame[y1 + m][x1 + n] = rgb;
+ }
}
}
}
uint32_t rgb =
((((colour & 7) * 0x49) & 0x1fe) << 15) |
((((colour & 0x38) * 0x49) & 0xff0) << 4) |
- ((((colour & 0xc0) * 0x55) & 0x3fc0) >> 6) |
+ (((colour & 0xc0) * 0x55) >> 6) | // 0x3fc0 >> 6
0xff000000;
x1 *= WINDOW_X_SCALE;
for (int l = 0; l < WINDOW_Y_SCALE; ++l)
uint32_t rgb =
((((colour & 7) * 0x49) & 0x1fe) << 15) |
((((colour & 0x38) * 0x49) & 0xff0) << 4) |
- ((((colour & 0xc0) * 0x55) & 0x3fc0) >> 6) |
+ (((colour & 0xc0) * 0x55) >> 6) | // 0x3fc0 >> 6
0xff000000;
x1 *= WINDOW_X_SCALE;
for (int l = 0; l < WINDOW_Y_SCALE; ++l)