From 9407d864c973b292b5590d90d15c88ac590d0ef2 Mon Sep 17 00:00:00 2001 From: MikeDX Date: Sun, 2 Aug 2026 12:10:12 +0100 Subject: [PATCH 1/2] Add PC Engine Chase game and graphics support - Introduced chase_gfx.h and chase.c for the Chase game port on PC Engine, including tile and sprite definitions. - Added gfxtest_gfx.h and gfxtest.c for a graphics smoke test, demonstrating background tiles and sprite functionality. - Implemented pcegfx.h, pcegfx.c, and pcegfx_tia.s for low-level graphics handling, including VRAM management and sprite updates. - Created perftest.c to benchmark graphics performance, isolating various workloads and measuring efficiency. - Ensured compatibility with the PC Engine's graphics capabilities and optimized for performance during gameplay. --- presets/pce/chase.c | 579 ++++++++++++++++++++++++++++++++ presets/pce/chase_gfx.h | 180 ++++++++++ presets/pce/gfxtest.c | 123 +++++++ presets/pce/gfxtest_gfx.h | 51 +++ presets/pce/pcegfx.c | 265 +++++++++++++++ presets/pce/pcegfx.h | 154 +++++++++ presets/pce/pcegfx_tia.s | 361 ++++++++++++++++++++ presets/pce/perftest.c | 290 ++++++++++++++++ presets/pce/solarian.c | 671 +++++++++++++++++++++++++++++++++++++ presets/pce/solarian_gfx.h | 224 +++++++++++++ src/platform/pce.ts | 4 + 11 files changed, 2902 insertions(+) create mode 100644 presets/pce/chase.c create mode 100644 presets/pce/chase_gfx.h create mode 100644 presets/pce/gfxtest.c create mode 100644 presets/pce/gfxtest_gfx.h create mode 100644 presets/pce/pcegfx.c create mode 100644 presets/pce/pcegfx.h create mode 100644 presets/pce/pcegfx_tia.s create mode 100644 presets/pce/perftest.c create mode 100644 presets/pce/solarian.c create mode 100644 presets/pce/solarian_gfx.h diff --git a/presets/pce/chase.c b/presets/pce/chase.c new file mode 100644 index 000000000..cb65c74a1 --- /dev/null +++ b/presets/pce/chase.c @@ -0,0 +1,579 @@ +/* + * Chase for PC Engine — 1:1 port of Shiru's NES Chase + * (presets/nes/chase), same Actor/FP/AI/levels as presets/mcr/chase.c. + * + * NES cells are 16×16; PCE uses 2×2 of 8×8 BAT tiles per cell and 16×16 + * sprites so the playfield is 16×13 cells on a 256×224 screen (MAP_Y0=1). + * + * Gfx: scripts/gen_pce_chase_gfx.py ← presets/nes/chase/tileset.chr + * Controls: pad move, I / RUN = start / continue / pause + */ +//#resource "pcegfx.h" +//#resource "chase_gfx.h" +//#link "pcegfx.c" +//#link "pcegfx_tia.s" + +#include +#include +#include "pcegfx.h" +#include "chase_gfx.h" + +#define TILE0 PCE_TILE_BASE +#define SPR0 PCE_SPR_BASE + +#define MAP_W 16 +#define MAP_H 13 +#define MAP_Y0 1 /* tile-rows above map[0] (HUD) */ +#define LEVELS_ALL 5 +#define ACTORS_MAX 4 + +#define TILE_SIZE 16 +#define TILE_SIZE_BIT 4 +#define FP_BITS 4 +#define TILE_TO_POS(t) ((word)(t) << (TILE_SIZE_BIT + FP_BITS)) +#define POS_TO_TILE(p) ((byte)((p) >> (TILE_SIZE_BIT + FP_BITS))) + +#define T_BLANK 0 +#define T_FLOOR 1 +#define T_WALL 2 +#define T_ITEM 3 + +#define DIR_NONE 0 +#define DIR_LEFT 1 +#define DIR_RIGHT 2 +#define DIR_UP 4 +#define DIR_DOWN 8 + +byte joy_left, joy_right, joy_up, joy_down, joy_fire; +byte fire_prev; + +typedef struct { + word x, y, cnt, speed; + byte dir, kind, wait; +} Actor; + +/* NES levels — 16×13, from nametables (same strings as MCR port). */ +const char* const levels[LEVELS_ALL][MAP_H] = { + { + " ", + " ", + " ######## ", + " #P*****# ", + " #*####*# ", + " #******# ", + " #*####*# ", + " #*****1# ", + " ######## ", + " ", + " ", + " ", + " ", + }, + { + " ", + " ########## ", + " #P***#**1# ", + " #*##*#*#*# ", + " #********# ", + " ###*#*#*## ", + " #********# ", + " #*#*#*##*# ", + " #2*******# ", + " ########## ", + " ", + " ", + " ", + }, + { + " ", + " ########## ", + " #P***#**1# ", + " ###*##*#*#*### ", + " #********#***# ", + " #*#*#*##*#*#*# ", + " #***#********# ", + " ###*#*#*##*### ", + " #***#***2# ", + " ########## ", + " ", + " ", + " ", + }, + { + " ###### ", + " #P***####### ", + " #*##*#****1# ", + " ###*##*#*#*#*# ", + " #**********#*# ", + " #*#*#*##*#*#*# ", + " #*#**********# ", + " #*#*#*#*##*### ", + " #2****#*##*# ", + " #######***3# ", + " ###### ", + " ", + " ", + }, + { + " ############ ", + " #P********1# ", + "###*##*##*##*###", + "#**************#", + "##*#*###*#*#*#*#", + "#*****#********#", + "#*###*#*#*###*##", + "#*******#******#", + "##*#*#*###*#*#*#", + "#**************#", + "###*##*##*##*###", + " #2********3# ", + " ############ ", + } +}; + +byte map[MAP_W * MAP_H]; +Actor actors[ACTORS_MAX]; +byte actor_n; +byte game_level, game_lives, items_count, items_collected; +byte game_clear, game_done, game_paused, spawn_wait; +word rnd = 0xCACE; +byte frame_cnt; + +/* Gem locations for cheap sparkle anim (avoid scanning the whole map). */ +byte gem_x[64], gem_y[64]; +byte gem_n; + +byte rand8(void) { + rnd = (word)(rnd * 0x41C6 + 0x5B3F); + return (byte)(rnd >> 8); +} + +void read_controls(void) { + unsigned char j = joy_read(JOY_1); + joy_left = JOY_LEFT(j) ? 1 : 0; + joy_right = JOY_RIGHT(j) ? 1 : 0; + joy_up = JOY_UP(j) ? 1 : 0; + joy_down = JOY_DOWN(j) ? 1 : 0; + joy_fire = (JOY_BTN_I(j) || JOY_RUN(j)) ? 1 : 0; +} + +byte map_at(byte x, byte y) { + if (x >= MAP_W || y >= MAP_H) return T_WALL; + return map[y * MAP_W + x]; +} + +void map_set(byte x, byte y, byte t) { + map[y * MAP_W + x] = t; +} + +byte font_code(char ch) { + if (ch >= '0' && ch <= '9') return (byte)(TILE_DIGIT + (ch - '0')); + if (ch >= 'a' && ch <= 'z') ch = (char)(ch - 32); + if (ch >= 'A' && ch <= 'Z') return (byte)(TILE_LETTER + (ch - 'A')); + if (ch == ':') return TILE_COLON; + if (ch == '/') return TILE_SLASH; + return TILE_EMPTY; +} + +void put_char(byte x, byte y, char ch) { + pce_put_tile(x, y, PCE_BAT(TILE0 + font_code(ch), 0)); +} + +void put_string(byte x, byte y, const char* s) { + while (*s) put_char(x++, y, *s++); +} + +void put_digit(byte x, byte y, byte d) { + pce_put_tile(x, y, PCE_BAT(TILE0 + TILE_DIGIT + (d % 10), 0)); +} + +void hide_all_sprites(void) { + byte i; + for (i = 0; i < ACTORS_MAX; i++) + PCE_SPR_HIDE(i); + pce_satb_update_n(ACTORS_MAX); +} + +void set_cell_tiles(byte mx, byte my, byte tl, byte tr, byte bl, byte br) { + byte sx = (byte)(mx << 1); + byte sy = (byte)((byte)(MAP_Y0 + my) << 1); + static word row[2]; + word addr = PCE_BAT_ADDR_XY(sx, sy); + row[0] = PCE_BAT(TILE0 + tl, 0); + row[1] = PCE_BAT(TILE0 + tr, 0); + pce_vram_burst(addr, row, 4); + row[0] = PCE_BAT(TILE0 + bl, 0); + row[1] = PCE_BAT(TILE0 + br, 0); + pce_vram_burst((word)(addr + PCE_BAT_W), row, 4); +} + +byte gem_spark; + +/* Gem cells always BAT-point at TILE_GEM0_*; sparkle rewrites those + * 4 tile patterns in VRAM (128 bytes) so every gem flips at once. */ +void gem_set_frame(byte spark) { + const unsigned char *src = + spark ? &chase_tiles[TILE_GEM1_TL * 32] + : &chase_tiles[TILE_GEM0_TL * 32]; + gem_spark = spark; + pce_load_tiles(TILE0 + TILE_GEM0_TL, src, 4); +} + +void draw_cell(byte x, byte y) { + byte t = map_at(x, y); + if (t == T_WALL) + set_cell_tiles(x, y, TILE_WALL_TL, TILE_WALL_TR, TILE_WALL_BL, TILE_WALL_BR); + else if (t == T_ITEM) + set_cell_tiles(x, y, TILE_GEM0_TL, TILE_GEM0_TR, TILE_GEM0_BL, TILE_GEM0_BR); + else if (t == T_FLOOR) + set_cell_tiles(x, y, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR); + else + set_cell_tiles(x, y, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY); +} + +void draw_hud(void) { + put_string(2, 0, "LEVEL:"); + put_digit(8, 0, (byte)(game_level + 1)); + put_string(10, 0, "GEMS:"); + put_digit(15, 0, (byte)(items_collected / 100)); + put_digit(16, 0, (byte)((items_collected / 10) % 10)); + put_digit(17, 0, (byte)(items_collected % 10)); + put_char(18, 0, '/'); + put_digit(19, 0, (byte)(items_count / 100)); + put_digit(20, 0, (byte)((items_count / 10) % 10)); + put_digit(21, 0, (byte)(items_count % 10)); + put_string(23, 0, "LIVES:"); + put_digit(29, 0, game_lives > 0 ? (byte)(game_lives - 1) : 0); +} + +byte can_enter(byte tx, byte ty) { + byte t = map_at(tx, ty); + return t == T_FLOOR || t == T_ITEM; +} + +void actor_try_dir(byte id, byte dir) { + Actor* a = &actors[id]; + byte tx = POS_TO_TILE(a->x); + byte ty = POS_TO_TILE(a->y); + if (dir == DIR_LEFT) tx--; + else if (dir == DIR_RIGHT) tx++; + else if (dir == DIR_UP) ty--; + else if (dir == DIR_DOWN) ty++; + else return; + if (!can_enter(tx, ty)) return; + a->dir = dir; + a->cnt = (word)TILE_SIZE << FP_BITS; +} + +void gem_remove_at(byte tx, byte ty) { + byte i; + for (i = 0; i < gem_n; i++) { + if (gem_x[i] == tx && gem_y[i] == ty) { + gem_n--; + gem_x[i] = gem_x[gem_n]; + gem_y[i] = gem_y[gem_n]; + return; + } + } +} + +void try_collect(byte id) { + byte tx, ty; + Actor* a = &actors[id]; + if (id != 0 || a->wait) return; + tx = POS_TO_TILE(a->x); + ty = POS_TO_TILE(a->y); + if (map_at(tx, ty) != T_ITEM) return; + map_set(tx, ty, T_FLOOR); + gem_remove_at(tx, ty); + draw_cell(tx, ty); + items_collected++; + draw_hud(); +} + +void load_level(byte li) { + byte x, y; + const char* row; + actor_n = 0; + items_count = 0; + items_collected = 0; + gem_n = 0; + game_level = li; + gem_set_frame(0); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + hide_all_sprites(); + for (y = 0; y < MAP_H; y++) { + row = levels[li][y]; + for (x = 0; x < MAP_W; x++) { + char c = row[x]; + byte t = T_BLANK; + if (c == '#') t = T_WALL; + else if (c == '*') { + t = T_ITEM; + items_count++; + if (gem_n < 64) { + gem_x[gem_n] = x; + gem_y[gem_n] = y; + gem_n++; + } + } + else if (c == 'P' || c == '1' || c == '2' || c == '3') { + Actor* a = &actors[actor_n]; + a->x = TILE_TO_POS(x); + a->y = TILE_TO_POS(y); + a->cnt = 0; + a->dir = DIR_NONE; + if (c == 'P') { + a->kind = 0; + a->speed = (word)(2 << FP_BITS); + a->wait = 16; + } else { + a->kind = (byte)(c - '0'); + a->speed = (word)(10 + ((a->kind - 1) << 1)); + a->wait = (byte)(16 + (a->kind << 4)); + } + actor_n++; + t = T_FLOOR; + } else if (c == '.') { + t = T_FLOOR; + } else { + t = T_BLANK; + } + map[y * MAP_W + x] = t; + } + } + for (y = 0; y < MAP_H; y++) + for (x = 0; x < MAP_W; x++) + draw_cell(x, y); + spawn_wait = (byte)(actor_n << 4); +} + +void draw_actors(void) { + byte i; + word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); + for (i = 0; i < ACTORS_MAX; i++) + PCE_SPR_HIDE(i); + for (i = 0; i < actor_n; i++) { + Actor* a = &actors[i]; + word px = (word)(PCE_SPR_X0 + (a->x >> FP_BITS)); + word py = (word)(PCE_SPR_Y0 + (MAP_Y0 * TILE_SIZE) + (a->y >> FP_BITS)); + byte shape; + if (a->wait && (a->wait >= 16 || (a->wait & 2))) + continue; + if (a->kind == 0) + shape = (frame_cnt & 8) ? SPR_PLAYER2 : SPR_PLAYER; + else + shape = SPR_ENEMY; + PCE_SPR_SET(i, px, py, PCE_SPR_PATTERN(shape), attr); + } + pce_satb_update_n(ACTORS_MAX); +} + +byte hit_player(void) { + byte i; + word px = actors[0].x >> FP_BITS; + word py = actors[0].y >> FP_BITS; + if (actors[0].wait) return 0; + for (i = 1; i < actor_n; i++) { + word ex, ey; + if (actors[i].wait) continue; + ex = actors[i].x >> FP_BITS; + ey = actors[i].y >> FP_BITS; + /* NES 4..12 box inside 16×16 */ + if (!((px + 4) >= (ex + 12) || (ex + 4) >= (px + 12) || + (py + 4) >= (ey + 12) || (ey + 4) >= (py + 12))) + return 1; + } + return 0; +} + +/* One 128-byte CHR upload flips every gem; BAT stays put. */ +void animate_gems(void) { + byte spark = (frame_cnt & 16) != 0; + if (spark != gem_spark) + gem_set_frame(spark); +} + +void enemy_ai(byte id) { + Actor* a = &actors[id]; + byte tx = POS_TO_TILE(a->x); + byte ty = POS_TO_TILE(a->y); + byte dirs[4]; + byte n = 0; + byte prev = a->dir; + if (prev != DIR_RIGHT && can_enter((byte)(tx - 1), ty)) dirs[n++] = DIR_LEFT; + if (prev != DIR_LEFT && can_enter((byte)(tx + 1), ty)) dirs[n++] = DIR_RIGHT; + if (prev != DIR_DOWN && can_enter(tx, (byte)(ty - 1))) dirs[n++] = DIR_UP; + if (prev != DIR_UP && can_enter(tx, (byte)(ty + 1))) dirs[n++] = DIR_DOWN; + if (!n) return; + actor_try_dir(id, dirs[rand8() % n]); + if (n > 1) { + Actor* p = &actors[0]; + if (prev != DIR_DOWN && p->y < a->y) actor_try_dir(id, DIR_UP); + if (prev != DIR_UP && p->y > a->y) actor_try_dir(id, DIR_DOWN); + if (prev != DIR_RIGHT && p->x < a->x) actor_try_dir(id, DIR_LEFT); + if (prev != DIR_LEFT && p->x > a->x) actor_try_dir(id, DIR_RIGHT); + } +} + +void player_controls(void) { + byte j = 0; + Actor* a = &actors[0]; + if (joy_left) j |= DIR_LEFT; + if (joy_right) j |= DIR_RIGHT; + if (joy_up) j |= DIR_UP; + if (joy_down) j |= DIR_DOWN; + if (j & a->dir) { + j = (byte)(j & ~a->dir); + actor_try_dir(0, a->dir); + } + if (j & DIR_LEFT) actor_try_dir(0, DIR_LEFT); + if (j & DIR_RIGHT) actor_try_dir(0, DIR_RIGHT); + if (j & DIR_UP) actor_try_dir(0, DIR_UP); + if (j & DIR_DOWN) actor_try_dir(0, DIR_DOWN); +} + +void advance_actor(byte id) { + Actor* a = &actors[id]; + word step; + if (!a->cnt) return; + step = a->speed; + if (step > a->cnt) step = a->cnt; + if (a->dir == DIR_LEFT) a->x -= step; + else if (a->dir == DIR_RIGHT) a->x += step; + else if (a->dir == DIR_UP) a->y -= step; + else if (a->dir == DIR_DOWN) a->y += step; + a->cnt -= step; + if (!a->cnt) { + a->x &= 0xff00; + a->y &= 0xff00; + try_collect(id); + } +} + +void wait_frame(void) { pce_wait_vsync(); } + +void wait_frames(byte n) { + while (n--) wait_frame(); +} + +void wait_for_fire(void) { + read_controls(); + while (!joy_fire) { wait_frame(); read_controls(); } + while (joy_fire) { wait_frame(); read_controls(); } +} + +void setup_gfx(void) { + pce_gfx_init(); + pce_disp_off(); + pce_load_palette(0, chase_bg_pal, 16); + pce_load_palette(256, chase_spr_pal, 16); + pce_load_tiles(TILE0, chase_tiles, CHASE_NTILE); + pce_load_sprites(SPR0, chase_sprites, CHASE_NSPR); + pce_satb_clear(); + pce_satb_update(); + pce_disp_on(); +} + +void title_screen(void) { + hide_all_sprites(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + put_string(13, 10, "CHASE"); + put_string(9, 14, "PRESS RUN / I"); + wait_for_fire(); +} + +void show_level_banner(void) { + hide_all_sprites(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + put_string(11, 12, "LEVEL"); + put_digit(17, 12, (byte)(game_level + 1)); + wait_frames(50); +} + +void show_game_over(void) { + hide_all_sprites(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + put_string(11, 12, "GAME OVER"); + wait_for_fire(); +} + +void show_well_done(void) { + hide_all_sprites(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + put_string(11, 12, "WELL DONE"); + wait_for_fire(); +} + +void game_loop(void) { + byte i; + hide_all_sprites(); + load_level(game_level); + draw_hud(); + game_done = 0; + game_clear = 0; + game_paused = 0; + frame_cnt = 0; + fire_prev = 1; + while (!game_done) { + wait_frame(); + /* Post-DMA vblank: BAT + sprites */ + animate_gems(); + draw_actors(); + + frame_cnt++; + read_controls(); + if (joy_fire && !fire_prev) { + game_paused = !game_paused; + draw_hud(); + } + fire_prev = joy_fire; + if (game_paused) continue; + + if (items_collected >= items_count && !game_clear) { + game_clear = 1; + game_done = 1; + } + + if (spawn_wait) --spawn_wait; + + for (i = 0; i < actor_n; i++) { + if (actors[i].wait) { + actors[i].wait--; + continue; + } + if (spawn_wait) continue; + advance_actor(i); + if (!actors[i].cnt) { + if (i == 0) player_controls(); + else enemy_ai(i); + } + } + if (!game_clear && hit_player()) { + game_done = 1; + wait_frames(60); + } + } + if (game_clear) wait_frames(50); + hide_all_sprites(); +} + +int main(void) { + joy_install(joy_static_stddrv); + setup_gfx(); + + for (;;) { + title_screen(); + game_level = 0; + game_lives = 4; + while (game_lives && game_level < LEVELS_ALL) { + show_level_banner(); + game_loop(); + if (game_clear) game_level++; + else game_lives--; + } + if (!game_lives) show_game_over(); + else show_well_done(); + } + return 0; +} diff --git a/presets/pce/chase_gfx.h b/presets/pce/chase_gfx.h new file mode 100644 index 000000000..5244f0ac1 --- /dev/null +++ b/presets/pce/chase_gfx.h @@ -0,0 +1,180 @@ +/* Auto-generated by scripts/gen_pce_chase_gfx.py — do not edit */ +#ifndef CHASE_GFX_H +#define CHASE_GFX_H + +#define CHASE_NTILE 58 +#define CHASE_NSPR 3 + +#define TILE_EMPTY 0 +#define TILE_FLOOR 1 +#define TILE_WALL_TL 2 +#define TILE_WALL_TR 3 +#define TILE_WALL_BL 4 +#define TILE_WALL_BR 5 +#define TILE_GEM0_TL 6 +#define TILE_GEM0_TR 7 +#define TILE_GEM0_BL 8 +#define TILE_GEM0_BR 9 +#define TILE_GEM1_TL 10 +#define TILE_GEM1_TR 11 +#define TILE_GEM1_BL 12 +#define TILE_GEM1_BR 13 +#define TILE_DIGIT 16 +#define TILE_COLON 26 +#define TILE_SLASH 27 +#define TILE_LETTER 32 + +#define SPR_PLAYER 0 +#define SPR_PLAYER2 1 +#define SPR_ENEMY 2 + +const unsigned char chase_tiles[1856] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x7F, 0xFF, 0x7F, 0xE0, 0x7F, 0xEF, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0xFC, 0xFE, 0xFA, 0xFC, 0x06, 0xF8, 0xF6, 0xF8, 0x16, 0xE8, 0x16, 0xE8, 0x16, 0xE8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE8, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, 0xEF, 0x78, 0xE0, 0x7F, 0xDF, 0x60, 0xBF, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0xE8, 0x16, 0xE8, 0x16, 0xE8, 0xF6, 0x08, 0x06, 0xF8, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0xAC, 0x00, 0x58, 0x03, 0xA3, 0x07, 0x53, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0x2E, 0x00, 0x1E, 0xC0, 0x8E, 0xE0, 0x40, 0xA0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE2, 0x07, 0xE1, 0x06, 0xE0, 0x03, 0x00, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8A, 0x20, 0x05, 0x20, 0x0A, 0xC0, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x04, 0x00, 0xA8, 0x03, 0x53, 0x07, 0xA3, 0x07, 0x52, 0x07, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0x0E, 0xC0, 0x8E, 0xE0, 0x4E, 0xA0, 0x80, 0x20, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE1, 0x06, 0xE0, 0x03, 0xE8, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x20, 0x05, 0xC0, 0x2A, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x38, 0x38, 0x78, 0x78, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7C, 0x7C, 0x7C, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0x7E, 0x7E, 0x0E, 0x0E, 0x7E, 0x7E, 0xFC, 0xFC, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0xFC, 0xFE, 0xFE, 0x0E, 0x0E, 0x3C, 0x3C, 0x3E, 0x3E, 0x0E, 0x0E, 0xFE, 0xFE, 0xFC, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x3E, 0x7E, 0x7E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE, 0x0E, 0x0E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0xFC, 0xFC, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE, 0xFE, 0xFC, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0xFC, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7E, 0x7E, 0x0E, 0x0E, 0x3E, 0x3E, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7E, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC6, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xCE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFC, 0x00, 0xE0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0xFE, 0x00, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x0E, 0x00, 0xFE, 0x00, 0xFC, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xC6, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xFE, 0x00, 0xFE, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char chase_sprites[384] = { + 0x00, 0x00, 0xFC, 0x3F, 0x06, 0x60, 0xF2, 0x5F, 0xF2, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, + 0xFA, 0x5F, 0xF2, 0x5F, 0xF2, 0x5F, 0xE2, 0x47, 0xE6, 0x67, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0xFC, 0x3F, 0x8C, 0x31, 0xB4, 0x2D, 0x94, 0x29, 0x94, 0x29, + 0x84, 0x21, 0xFC, 0x3F, 0xFC, 0x3F, 0x1C, 0x38, 0xD8, 0x1B, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFC, 0x3F, 0x06, 0x60, 0xF2, 0x5F, 0xF2, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, + 0xF2, 0x5F, 0xF2, 0x5F, 0xE2, 0x47, 0xE6, 0x67, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x1F, 0xFC, 0x3F, 0x8C, 0x31, 0xB4, 0x2D, 0x94, 0x29, 0x94, 0x29, 0x84, 0x21, + 0xFC, 0x3F, 0xFC, 0x3F, 0x1C, 0x38, 0xD8, 0x1B, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x7F, 0x02, 0x40, 0xF2, 0x5F, 0xFE, 0x7F, 0xFA, 0x5F, 0x7A, 0x5E, 0xFA, 0x5F, + 0xFA, 0x5F, 0xF2, 0x5F, 0xF2, 0x5F, 0xD2, 0x4B, 0xE6, 0x67, 0xFC, 0x3F, 0xF8, 0x1F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, 0x04, 0x20, 0x94, 0x29, 0x94, 0x29, + 0xB4, 0x2D, 0x8C, 0x31, 0xFC, 0x3F, 0x3C, 0x3C, 0x98, 0x19, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned short chase_bg_pal[16] = { 0x000, 0x04E, 0x1B6, 0x1FF, 0x000, 0x0B6, 0x16E, 0x1B6, 0x000, 0x048, 0x0E8, 0x1F0, 0x000, 0x04E, 0x096, 0x1DE }; +const unsigned short chase_spr_pal[16] = { 0x000, 0x000, 0x1C8, 0x1FF, 0x000, 0x000, 0x1C4, 0x1FF, 0x000, 0x000, 0x1A4, 0x1FF, 0x000, 0x000, 0x096, 0x1FF }; + +#endif diff --git a/presets/pce/gfxtest.c b/presets/pce/gfxtest.c new file mode 100644 index 000000000..5530d7e0b --- /dev/null +++ b/presets/pce/gfxtest.c @@ -0,0 +1,123 @@ +/* + * PC Engine graphics smoke test — BG tiles + bouncing sprites. + * + * Proves the pcegfx SDK (not conio). Pad moves the ship; ball/alien bounce. + */ +//#resource "pcegfx.h" +//#resource "gfxtest_gfx.h" +//#link "pcegfx.c" +//#link "pcegfx_tia.s" + +#include +#include "pcegfx.h" +#include "gfxtest_gfx.h" + +#define TILE0 PCE_TILE_BASE +#define SPR0 PCE_SPR_BASE + +static word ship_x, ship_y; +static word ball_x, ball_y; +static sbyte ball_dx, ball_dy; +static word alien_x, alien_y; +static sbyte alien_dx; + +static void draw_playfield(void) { + byte x, y; + + /* sky */ + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + 1, 0)); + + /* checker floor */ + for (y = 24; y < 28; ++y) + for (x = 0; x < 32; ++x) + pce_put_tile(x, y, PCE_BAT(TILE0 + 2, 0)); + + /* brick border */ + pce_fill_bat(0, 0, 32, 1, PCE_BAT(TILE0 + 3, 0)); + pce_fill_bat(0, 23, 32, 1, PCE_BAT(TILE0 + 3, 0)); + for (y = 1; y < 23; ++y) { + pce_put_tile(0, y, PCE_BAT(TILE0 + 3, 0)); + pce_put_tile(31, y, PCE_BAT(TILE0 + 3, 0)); + } + + /* stars */ + pce_put_tile(4, 3, PCE_BAT(TILE0 + 4, 0)); + pce_put_tile(12, 5, PCE_BAT(TILE0 + 4, 0)); + pce_put_tile(20, 2, PCE_BAT(TILE0 + 4, 0)); + pce_put_tile(27, 6, PCE_BAT(TILE0 + 4, 0)); + pce_put_tile(8, 10, PCE_BAT(TILE0 + 4, 0)); + pce_put_tile(22, 12, PCE_BAT(TILE0 + 4, 0)); +} + +static void setup_gfx(void) { + pce_gfx_init(); + pce_disp_off(); + + pce_load_palette(0, gfxtest_bg_pal, 16); + pce_load_palette(256, gfxtest_spr_pal, 16); + + pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_load_sprites(SPR0, gfxtest_sprites, GFXTEST_NSPR); + + draw_playfield(); + + ship_x = PCE_SPR_X0 + 120; + ship_y = PCE_SPR_Y0 + 180; + ball_x = PCE_SPR_X0 + 80; + ball_y = PCE_SPR_Y0 + 40; + ball_dx = 2; + ball_dy = 1; + alien_x = PCE_SPR_X0 + 40; + alien_y = PCE_SPR_Y0 + 60; + alien_dx = 1; + + pce_satb_clear(); + pce_spr_set(0, ship_x, ship_y, PCE_SPR_PATTERN(0), PCE_SPR_PRI | PCE_SPR_PAL(0)); + pce_spr_set(1, ball_x, ball_y, PCE_SPR_PATTERN(1), PCE_SPR_PRI | PCE_SPR_PAL(0)); + pce_spr_set(2, alien_x, alien_y, PCE_SPR_PATTERN(2), PCE_SPR_PRI | PCE_SPR_PAL(0)); + pce_satb_update(); + pce_disp_on(); +} + +static void update_sprites(void) { + unsigned char pad = joy_read(JOY_1); + + if (JOY_LEFT(pad) && ship_x > PCE_SPR_X0 + 8) + ship_x -= 2; + if (JOY_RIGHT(pad) && ship_x < PCE_SPR_X0 + 256 - 24) + ship_x += 2; + if (JOY_UP(pad) && ship_y > PCE_SPR_Y0 + 8) + ship_y -= 2; + if (JOY_DOWN(pad) && ship_y < PCE_SPR_Y0 + 224 - 24) + ship_y += 2; + + ball_x += ball_dx; + ball_y += ball_dy; + if (ball_x <= PCE_SPR_X0 + 8 || ball_x >= PCE_SPR_X0 + 256 - 24) + ball_dx = -ball_dx; + if (ball_y <= PCE_SPR_Y0 + 8 || ball_y >= PCE_SPR_Y0 + 224 - 40) + ball_dy = -ball_dy; + + alien_x += alien_dx; + if (alien_x <= PCE_SPR_X0 + 8 || alien_x >= PCE_SPR_X0 + 256 - 24) + alien_dx = -alien_dx; + + { + word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); + PCE_SPR_SET(0, ship_x, ship_y, PCE_SPR_PATTERN(0), attr); + PCE_SPR_SET(1, ball_x, ball_y, PCE_SPR_PATTERN(1), attr); + PCE_SPR_SET(2, alien_x, alien_y, PCE_SPR_PATTERN(2), attr); + } + pce_satb_update_n(3); +} + +int main(void) { + joy_install(joy_static_stddrv); + setup_gfx(); + + for (;;) { + pce_wait_vsync(); + update_sprites(); + } + return 0; +} diff --git a/presets/pce/gfxtest_gfx.h b/presets/pce/gfxtest_gfx.h new file mode 100644 index 000000000..928c2de3e --- /dev/null +++ b/presets/pce/gfxtest_gfx.h @@ -0,0 +1,51 @@ +/* Auto-generated by scripts/gen_pce_gfxtest_gfx.py — do not edit */ +#ifndef GFXTEST_GFX_H +#define GFXTEST_GFX_H + +#define GFXTEST_NTILE 5 +#define GFXTEST_NSPR 3 + +const unsigned char gfxtest_tiles[160] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x88, 0xFF, 0x88, 0xFF, 0x88, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEF, 0x00, 0xEF, 0x00, 0xC7, 0x00, 0x83, 0x00, 0xC7, 0x00, 0xEF, 0x00, 0xEF, 0x00, 0xFF, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, +}; + +const unsigned char gfxtest_sprites[384] = { + 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x07, 0x60, 0x06, 0xF0, 0x0F, 0xF0, 0x0F, 0x78, 0x1E, + 0x78, 0x1E, 0xFC, 0x3F, 0xDC, 0x3B, 0x8E, 0x71, 0x86, 0x61, 0x80, 0x01, 0x40, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x40, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x03, 0xF0, 0x0F, 0xF8, 0x1F, 0x1C, 0x38, 0x0C, 0x30, 0x0E, 0x70, 0x0E, 0x70, + 0x0E, 0x70, 0x0E, 0x70, 0x0C, 0x30, 0x1C, 0x38, 0xF8, 0x1F, 0xF0, 0x0F, 0xC0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0xC0, 0x03, 0x30, 0x0C, 0x08, 0x10, 0xE4, 0x27, 0xF4, 0x29, 0xF2, 0x4B, 0xF2, 0x4F, + 0xF2, 0x4F, 0xF2, 0x4F, 0xF4, 0x2F, 0xE4, 0x27, 0x08, 0x10, 0x30, 0x0C, 0xC0, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x10, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x30, 0x0C, 0x60, 0x06, 0xF0, 0x0F, 0xF8, 0x1F, 0xEC, 0x37, 0xEC, 0x37, 0xFC, 0x3F, + 0xFC, 0x3F, 0x30, 0x0C, 0x18, 0x18, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned short gfxtest_bg_pal[16] = { 0x000, 0x049, 0x12E, 0x0B4, 0x1FF, 0x038, 0x1C0, 0x0FF, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short gfxtest_spr_pal[16] = { 0x000, 0x1FF, 0x038, 0x0E8, 0x1FF, 0x1C0, 0x049, 0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; + +#endif diff --git a/presets/pce/pcegfx.c b/presets/pce/pcegfx.c new file mode 100644 index 000000000..57932376d --- /dev/null +++ b/presets/pce/pcegfx.c @@ -0,0 +1,265 @@ +/* + * PC Engine VDC/VCE helpers — see pcegfx.h + * + * Performance notes (accurate emulators / real hardware): + * - Bulk VRAM uses HuC6280 TIA via pce_vram_burst / pce_tia_vdc. + * - SATB: write shadow → VRAM only; DCR auto-DMA copies each vblank. + * Do NOT rewrite register 19 every frame (forces an extra DMA + stalls). + * - Call BAT/SATB updates immediately after pce_wait_vsync() — it syncs on + * cc65's vdc_flags (IRQ clears VDC status) then waits out SATB DMA. + */ +#include "pcegfx.h" + +/* Mirror ports outside ZP ($00xx redirects to $20xx on HuC6280) */ +#define VDC_CTRL (*(volatile unsigned char *)0x0200) +#define VDC_DATA_LO (*(volatile unsigned char *)0x0202) +#define VDC_DATA_HI (*(volatile unsigned char *)0x0203) + +#define VCE_CTRL (*(volatile unsigned char *)0x0400) +#define VCE_ADDR_LO (*(volatile unsigned char *)0x0402) +#define VCE_ADDR_HI (*(volatile unsigned char *)0x0403) +#define VCE_DATA_LO (*(volatile unsigned char *)0x0404) +#define VCE_DATA_HI (*(volatile unsigned char *)0x0405) + +#define VDC_MAWR 0 +#define VDC_VWR 2 +#define VDC_CR 5 +#define VDC_BXR 7 +#define VDC_BYR 8 +#define VDC_MWR 9 +#define VDC_HSR 10 +#define VDC_HDR 11 +#define VDC_VSR 12 +#define VDC_VDR 13 +#define VDC_VCR 14 +#define VDC_DCR 15 +#define VDC_SATB 19 + +#define CR_BG 0x80 +#define CR_SPR 0x40 +#define CR_VBL 0x08 +#define CR_RCR 0x04 + +static unsigned char cr_lo; + +/* 64 sprites * 4 words — little-endian bytes match TIA upload order */ +unsigned char pce_satb[64 * 4 * 2]; + +/* fill pattern reused by fill_vram / fill_bat */ +static unsigned char fillbuf[64]; + +static void vdc_reg(unsigned char reg, word value) { + VDC_CTRL = reg; + VDC_DATA_LO = (unsigned char)value; + VDC_DATA_HI = (unsigned char)(value >> 8); +} + +static void apply_cr(void) { + vdc_reg(VDC_CR, cr_lo); +} + +void pce_disp_off(void) { + cr_lo = CR_VBL; + apply_cr(); +} + +void pce_bg_on(void) { + cr_lo |= CR_BG; + apply_cr(); +} + +void pce_spr_on(void) { + cr_lo |= CR_SPR; + apply_cr(); +} + +void pce_disp_on(void) { + cr_lo = CR_BG | CR_SPR | CR_VBL; + apply_cr(); +} + +void pce_scroll(word x, word y) { + vdc_reg(VDC_BXR, x); + vdc_reg(VDC_BYR, y); +} + +/* Asm: pcegfx_tia.s */ +void __fastcall__ pce_band_scroll_set(unsigned int bxr); +void __fastcall__ pce_band_scroll_enable(unsigned int top_rcr, unsigned int bot_rcr); +void pce_band_scroll_disable(void); + +void pce_band_enable(byte top_px, byte bot_px) { + /* RCR line 0 of active display is register value 64. */ + pce_band_scroll_enable((word)(64 + top_px), (word)(64 + bot_px)); + cr_lo |= CR_RCR; + apply_cr(); +} + +void pce_band_disable(void) { + pce_band_scroll_disable(); + cr_lo &= (unsigned char)~CR_RCR; + apply_cr(); +} + +void pce_band_set_x(word screen_shift) { + /* Increasing shift moves BG content to the right (BXR decreases). */ + pce_band_scroll_set((word)(0 - screen_shift) & 0x03FF); +} + +void pce_band_catchup(void); /* asm */ + +void pce_gfx_init(void) { + (void)VDC_CTRL; + + cr_lo = 0; + apply_cr(); + + vdc_reg(VDC_BXR, 0); + vdc_reg(VDC_BYR, 0); + vdc_reg(6, 0); /* RCR off */ + + /* + * MWR: 32x32 BAT (bits 4-6 = 000), 2-cycle CPU VRAM access (bits 0-1 = 01). + * MWR=0 (1-cycle) is unsafe after crt0's `csh` and stalls forever-ish on + * accurate cores when the VDC is busy. + */ + vdc_reg(VDC_MWR, 0x0001); + vdc_reg(VDC_HSR, 0x0202); + vdc_reg(VDC_HDR, 0x041F); + vdc_reg(VDC_VSR, 0x0D07); + vdc_reg(VDC_VDR, 0x00DF); + vdc_reg(VDC_VCR, 0x0003); + + /* Auto VRAM→SATB each vblank; set source once. */ + vdc_reg(VDC_DCR, 0x0010); + vdc_reg(VDC_SATB, PCE_SATB_ADDR); + + /* 5 MHz pixel clock (256-wide) */ + VCE_CTRL = 0x04; + + pce_fill_vram(PCE_BAT_ADDR, 0, PCE_BAT_W * PCE_BAT_H); + pce_fill_vram(0, 0, 16); + + pce_satb_clear(); + pce_satb_update(); + + cr_lo = CR_VBL; + apply_cr(); +} + +void pce_load_vram(word vaddr, const void *data, word nwords) { + if (!nwords) return; + pce_vram_burst(vaddr, data, (unsigned int)nwords << 1); +} + +void pce_fill_vram(word vaddr, word value, word nwords) { + unsigned char lo = (unsigned char)value; + unsigned char hi = (unsigned char)(value >> 8); + word i; + + if (!nwords) return; + + for (i = 0; i < 64; i += 2) { + fillbuf[i] = lo; + fillbuf[i + 1] = hi; + } + + while (nwords) { + word chunk = nwords > 32 ? 32 : nwords; + pce_vram_burst(vaddr, fillbuf, (unsigned int)chunk << 1); + vaddr += chunk; + nwords -= chunk; + } +} + +void pce_set_color(word index, word color) { + VCE_ADDR_LO = (unsigned char)index; + VCE_ADDR_HI = (unsigned char)(index >> 8); + VCE_DATA_LO = (unsigned char)color; + VCE_DATA_HI = (unsigned char)(color >> 8); +} + +void pce_load_palette(word index, const word *colors, word count) { + VCE_ADDR_LO = (unsigned char)index; + VCE_ADDR_HI = (unsigned char)(index >> 8); + while (count--) { + word c = *colors++; + VCE_DATA_LO = (unsigned char)c; + VCE_DATA_HI = (unsigned char)(c >> 8); + } +} + +void pce_load_tiles(word tile_index, const void *data, word ntiles) { + pce_load_vram((word)(tile_index << 4), data, (word)(ntiles << 4)); +} + +void pce_load_sprites(word pattern, const void *data, word npatterns) { + pce_load_vram((word)(pattern << 5), data, (word)(npatterns << 6)); +} + +void pce_put_tile(byte x, byte y, word bat) { + word w = bat; + pce_vram_burst(PCE_BAT_ADDR_XY(x, y), &w, 2); +} + +void pce_put_bat_row(byte x, byte y, const word *bats, byte n) { + if (!n) return; + pce_vram_burst(PCE_BAT_ADDR_XY(x, y), bats, (unsigned int)n << 1); +} + +void pce_fill_bat(byte x, byte y, byte w, byte h, word bat) { + byte row; + unsigned char lo = (unsigned char)bat; + unsigned char hi = (unsigned char)(bat >> 8); + byte i; + + for (i = 0; i < 64; i += 2) { + fillbuf[i] = lo; + fillbuf[i + 1] = hi; + } + + for (row = 0; row < h; ++row) { + word addr = PCE_BAT_ADDR_XY(x, (byte)(y + row)); + word left = w; + while (left) { + byte chunk = left > 32 ? 32 : (byte)left; + pce_vram_burst(addr, fillbuf, (unsigned int)chunk << 1); + addr += chunk; + left = (word)(left - chunk); + } + } +} + +void pce_load_bat(byte x, byte y, const word *map, byte w, byte h) { + byte row; + for (row = 0; row < h; ++row) { + pce_put_bat_row(x, (byte)(y + row), map, w); + map += w; + } +} + +void pce_satb_clear(void) { + word i; + for (i = 0; i < sizeof(pce_satb); ++i) + pce_satb[i] = 0; +} + +void pce_spr_hide(byte i) { + PCE_SPR_HIDE(i); +} + +void pce_spr_set(byte i, word x, word y, word pattern, word attr) { + PCE_SPR_SET(i, x, y, pattern, attr); +} + +void pce_satb_update(void) { + pce_satb_update_n(64); +} + +void pce_satb_update_n(byte n) { + if (!n) return; + if (n > 64) n = 64; + /* Copy shadow into VRAM SATB source. Auto-DMA (DCR bit4) ships it + * next vblank — do not poke register 19 here. */ + pce_vram_burst(PCE_SATB_ADDR, pce_satb, (unsigned int)n << 3); +} diff --git a/presets/pce/pcegfx.h b/presets/pce/pcegfx.h new file mode 100644 index 000000000..89d8230e3 --- /dev/null +++ b/presets/pce/pcegfx.h @@ -0,0 +1,154 @@ +/* + * Minimal PC Engine tile/sprite SDK for 8bitworkshop (cc65). + * + * Replaces conio for real VDC graphics: 256x224 BG, 16-color tiles, + * hardware sprites via a RAM SATB shadow + VRAM copy. + * + * Link with: + * //#link "pcegfx.c" + * //#link "pcegfx_tia.s" + * + * Do not include — conio's constructor reconfigures the VDC + * for text mode and will fight this library. + * + * Hot path: after pce_wait_vsync(), do BAT/SATB updates immediately. + * pce_satb_update* only copies into VRAM; DCR auto-DMA feeds the VDC. + */ +#ifndef PCEGFX_H +#define PCEGFX_H + +#include + +typedef unsigned char byte; +typedef signed char sbyte; +typedef unsigned short word; + +/* Default VRAM layout used by this SDK */ +#define PCE_BAT_ADDR 0x0000 +#define PCE_TILE_BASE 0x100 /* first BG tile index (VRAM 0x1000) */ +#define PCE_SPR_BASE 0x200 /* first sprite pattern (VRAM 0x4000; <<5) */ +#define PCE_SATB_ADDR 0x7F00 + +/* 16x16 sprite patterns are spaced by 2 in the SATB pattern field */ +#define PCE_SPR_PATTERN(i) ((word)(PCE_SPR_BASE + ((i) * 2))) + +#define PCE_BAT_W 32 +#define PCE_BAT_H 32 +#define PCE_SCREEN_W 256 +#define PCE_SCREEN_H 224 + +/* Sprite coordinates: visible top-left is (32, 64) */ +#define PCE_SPR_X0 32 +#define PCE_SPR_Y0 64 + +/* BAT word: low 12 = tile index, high 4 = BG palette */ +#define PCE_BAT(tile, pal) ((word)(tile) | ((word)(pal) << 12)) + +/* Sprite attribute word helpers */ +#define PCE_SPR_PRI 0x0080u +#define PCE_SPR_CGX 0x0100u /* 32px wide */ +#define PCE_SPR_CGY16 0x0000u +#define PCE_SPR_CGY32 0x1000u +#define PCE_SPR_CGY64 0x3000u +#define PCE_SPR_HFLIP 0x0800u +#define PCE_SPR_VFLIP 0x8000u +#define PCE_SPR_PAL(p) ((word)((p) & 0x0F)) + +/* VCE color: 9-bit gggrrrbbb in a 16-bit word */ +#define PCE_RGB(r, g, b) \ + ((word)((((g) & 7) << 6) | (((r) & 7) << 3) | ((b) & 7))) + +/* BAT address helpers (32-wide map → <<5, no multiply) */ +#define PCE_BAT_ADDR_XY(x, y) ((word)(((word)(byte)(y) << 5) + (byte)(x))) + +/* Init 256x224 / 32x32 BAT, tiles @0x1000, sprites @0x4000, SATB @0x7F00 */ +void pce_gfx_init(void); + +void pce_disp_off(void); +void pce_disp_on(void); /* BG + sprites + VBlank IRQ */ +void pce_bg_on(void); +void pce_spr_on(void); + +void pce_scroll(word x, word y); + +/* + * Mid-frame horizontal scroll band (RCR IRQ). + * Lines [top_px, bot_px) use BXR from pce_band_set_x(); elsewhere BXR=0. + * Call enable after pce_disp_on(). + */ +void pce_band_enable(byte top_px, byte bot_px); +void pce_band_disable(void); +void pce_band_set_x(word screen_shift); +/* After VB VRAM work: if top RCR was missed, force scrolled BXR now. */ +void pce_band_catchup(void); + +void pce_load_vram(word vaddr, const void *data, word nwords); +void pce_fill_vram(word vaddr, word value, word nwords); + +/* Palette index 0..255 BG, 256..511 sprites; count = # of colors */ +void pce_load_palette(word index, const word *colors, word count); +void pce_set_color(word index, word color); + +/* BG tiles: 32 bytes / 16 words each. tile_index is BAT character code. */ +void pce_load_tiles(word tile_index, const void *data, word ntiles); + +/* Sprite patterns: 128 bytes / 64 words each (16x16). pattern = VRAM>>5. */ +void pce_load_sprites(word pattern, const void *data, word npatterns); + +void pce_put_tile(byte x, byte y, word bat); +/* Burst-write `n` BAT words starting at (x,y) — one MAWR, then stream. */ +void pce_put_bat_row(byte x, byte y, const word *bats, byte n); +void pce_fill_bat(byte x, byte y, byte w, byte h, word bat); +void pce_load_bat(byte x, byte y, const word *map, byte w, byte h); + +/* Sprite attribute table (64 entries) kept in RAM; flush each frame. + * Prefer PCE_SPR_SET / PCE_SPR_HIDE macros on the hot path. */ +extern unsigned char pce_satb[64 * 4 * 2]; +void pce_satb_clear(void); +void pce_spr_hide(byte i); +void pce_spr_set(byte i, word x, word y, word pattern, word attr); +void pce_satb_update(void); +/* Upload only the first `n` SATB entries (n*4 words). Prefer this in-game. */ +void pce_satb_update_n(byte n); + +/* Direct SATB shadow writes (no call overhead) */ +#define PCE_SPR_HIDE(i) do { \ + unsigned char *_pce_s = &pce_satb[(unsigned)(i) * 8]; \ + _pce_s[0] = 0; _pce_s[1] = 0; \ +} while (0) + +#define PCE_SPR_SET(i, x, y, pattern, attr) do { \ + unsigned char *_pce_s = &pce_satb[(unsigned)(i) * 8]; \ + word _pce_x = (word)(x); \ + word _pce_y = (word)(y); \ + word _pce_p = (word)(pattern); \ + word _pce_a = (word)(attr); \ + _pce_s[0] = (unsigned char)_pce_y; \ + _pce_s[1] = (unsigned char)(_pce_y >> 8); \ + _pce_s[2] = (unsigned char)_pce_x; \ + _pce_s[3] = (unsigned char)(_pce_x >> 8); \ + _pce_s[4] = (unsigned char)_pce_p; \ + _pce_s[5] = (unsigned char)(_pce_p >> 8); \ + _pce_s[6] = (unsigned char)_pce_a; \ + _pce_s[7] = (unsigned char)(_pce_a >> 8); \ +} while (0) + +/* + * Wait for vblank (via cc65 vdc_flags — do NOT poll VDC status yourself), + * then briefly wait out SATB DMA. Do BAT/SATB uploads right after this. + */ +void pce_wait_vsync(void); +/* VB only (skip SATB-idle wait). For perftest A/B comparisons. */ +void pce_wait_vsync_vb(void); +/* Non-zero if a VB is pending in vdc_flags (does not consume it). */ +unsigned char pce_vb_pending(void); +/* Incremented when wait sees VB already pending (frame overrun). */ +extern unsigned short pce_vsync_overruns; +/* SATB-idle poll count from the last pce_wait_vsync() call. */ +extern unsigned short pce_busy_wait_iters; + +/* Low-level: MAWR+VWR+TIA in one asm call (nbytes is bytes, not words). */ +void __fastcall__ pce_vram_burst(unsigned int vaddr, const void *src, + unsigned int nbytes); + +#endif diff --git a/presets/pce/pcegfx_tia.s b/presets/pce/pcegfx_tia.s new file mode 100644 index 000000000..a195238f5 --- /dev/null +++ b/presets/pce/pcegfx_tia.s @@ -0,0 +1,361 @@ +; +; Fast VRAM upload via HuC6280 TIA. +; TIA alternates dest between $0202/$0203 for LSB/MSB VDC data writes. +; +; IMPORTANT: the TIA opcode lives in DATA (RAM). Patching a ROM-resident +; instruction is a no-op on HuCard and produces garbage VRAM uploads. +; + .setcpu "huc6280" + .export _pce_tia_vdc + .export _pce_vram_burst + .export _pce_wait_vsync + .export _pce_wait_vsync_vb + .export _pce_vb_pending + .export _pce_vsync_overruns + .export _pce_busy_wait_iters + .export _pce_band_scroll_set + .export _pce_band_scroll_enable + .export _pce_band_scroll_disable + .export _pce_band_catchup + .import popax + .importzp tmp1, tmp2, ptr1, vdc_flags + +VDC_CTRL = $0200 +VDC_DATA_LO = $0202 +VDC_DATA_HI = $0203 +STATUS_VB = $20 +STATUS_BUSY = $40 +STATUS_SATBEND = $08 +STATUS_RCR = $04 + +VDC_RCR = 6 +VDC_BXR = 7 + +; RAM trampoline: TIA + RTS (copied from ROM by crt0 with .DATA) +.segment "DATA" +tia_stub: + .byte $E3 ; TIA + .word $FFFF ; src (patched) + .word $0202 ; VDC data port + .word $FFFF ; length (patched) + .byte $60 ; RTS + +.segment "BSS" +_pce_vsync_overruns: + .res 2 ; word — byte wrapped mid-bench +_pce_busy_wait_iters: + .res 2 ; loops spent waiting out SATB DMA + +.segment "CODE" + +; Patch and run TIA. nbytes in tmp1/tmp2, src in ptr1. +.proc tia_run + lda ptr1 + sta tia_stub+1 + lda ptr1+1 + sta tia_stub+2 + lda tmp1 + sta tia_stub+5 + lda tmp2 + sta tia_stub+6 + jmp tia_stub +.endproc + +; void __fastcall__ pce_tia_vdc(const void *src, unsigned int nbytes); +; nbytes in A/X, src on soft stack. VWR must already be selected. +.proc _pce_tia_vdc + sta tmp1 + stx tmp2 + ora tmp2 + beq done + jsr popax + sta ptr1 + stx ptr1+1 + jsr tia_run +done: rts +.endproc + +; void __fastcall__ pce_vram_burst(unsigned int vaddr, const void *src, +; unsigned int nbytes); +; Sets MAWR + VWR, then TIA. nbytes in A/X; src then vaddr on soft stack. +.proc _pce_vram_burst + sta tmp1 + stx tmp2 + ora tmp2 + beq drain + + jsr popax + sta ptr1 + stx ptr1+1 + jsr popax ; vaddr + + ldy #0 ; MAWR + sty VDC_CTRL + sta VDC_DATA_LO + stx VDC_DATA_HI + ldy #2 ; VWR + sty VDC_CTRL + jmp tia_run + +; nbytes==0: still drop both pointer args +drain: jsr popax + jmp popax +.endproc + +; --------------------------------------------------------------------------- +; VBlank sync +; +; cc65's IRQStub reads VDC_CTRL (clearing status) into vdc_flags every IRQ. +; Polling VDC_CTRL directly therefore races the IRQ and can hang forever — +; that was freezing gfxtest/solarian/chase/perftest after a few frames. +; Always sync on vdc_flags instead. +; --------------------------------------------------------------------------- + +; Clear VB bit in vdc_flags (A, X clobbered). +.proc ack_vb_flag + lda vdc_flags + and #<~STATUS_VB + sta vdc_flags + rts +.endproc + +; Wait for next VB via vdc_flags. Increments overrun if already pending. +.proc wait_vb_edge + lda vdc_flags + and #STATUS_VB + beq wait_edge + inc _pce_vsync_overruns + bne :+ + inc _pce_vsync_overruns+1 +: jsr ack_vb_flag +wait_edge: + lda vdc_flags + and #STATUS_VB + beq wait_edge + jmp ack_vb_flag +.endproc + +; After VB: wait for SATB DMA end so TIA won't RDY-stall. +; Exit on SATBEND, or on BUSY falling after it was seen, or on a short +; timeout (~1k polls ≈ a few scanlines — not a whole frame). +; IMPORTANT: reading VDC_CTRL clears RCR — if that bit is set, run band +; catch-up so we don't drop a mid-frame BXR update. +.proc wait_satb_idle + stz _pce_busy_wait_iters + stz _pce_busy_wait_iters+1 + stz tmp1 ; busy-seen flag + ldy #4 ; 4 × 256 polls max +loop: + lda VDC_CTRL + sta tmp2 ; preserve status (X gets clobbered) + and #STATUS_RCR + beq :+ + jsr band_rcr_from_poll +: lda tmp2 + and #STATUS_SATBEND + bne done + lda tmp2 + and #STATUS_BUSY + beq not_busy + lda #1 + sta tmp1 + bra cont +not_busy: + lda tmp1 + bne done ; was busy, now clear +cont: + inc _pce_busy_wait_iters + bne loop + inc _pce_busy_wait_iters+1 + dey + bne loop +done: rts +.endproc + +.proc _pce_wait_vsync_vb + jmp wait_vb_edge +.endproc + +.proc _pce_wait_vsync + jsr wait_vb_edge + jmp wait_satb_idle +.endproc + +; unsigned char pce_vb_pending(void); +; Non-zero if vdc_flags still has VB set (does not acknowledge). +.proc _pce_vb_pending + lda vdc_flags + and #STATUS_VB + ldx #0 + rts +.endproc + +; --------------------------------------------------------------------------- +; Mid-frame BXR band scroll via RCR IRQ. +; Screen Y top/bot are converted by C to RCR values (64+Y) before enable. +; At VB: BXR=0, arm top. At top: BXR=band_bxr, arm bot. At bot: BXR=0, arm top. +; --------------------------------------------------------------------------- + +.segment "BSS" +band_enabled: + .res 1 +band_phase: + .res 1 ; 0 = expect top, 1 = expect bot +band_top_rcr: + .res 2 +band_bot_rcr: + .res 2 +band_bxr: + .res 2 + +.segment "CODE" + +.proc write_bxr + ldy #VDC_BXR + sty VDC_CTRL + sta VDC_DATA_LO + stx VDC_DATA_HI + rts +.endproc + +.proc write_rcr + ldy #VDC_RCR + sty VDC_CTRL + sta VDC_DATA_LO + stx VDC_DATA_HI + rts +.endproc + +; Enter scrolled band: BXR=band_bxr, phase=1, arm bot. +.proc band_apply_top + lda #1 + sta band_phase + lda band_bxr + ldx band_bxr+1 + jsr write_bxr + lda band_bot_rcr + ldx band_bot_rcr+1 + jmp write_rcr +.endproc + +; Leave scrolled band: BXR=0, phase=0, arm top. +.proc band_apply_bot + stz band_phase + lda #0 + tax + jsr write_bxr + lda band_top_rcr + ldx band_top_rcr+1 + jmp write_rcr +.endproc + +; Status poll stole an RCR edge — advance phase the same way the IRQ would. +.proc band_rcr_from_poll + lda band_enabled + beq :+ + lda band_phase + bne bot + jmp band_apply_top +bot: jmp band_apply_bot +: rts +.endproc + +; void __fastcall__ pce_band_scroll_set(unsigned int bxr); +; Updates shadow; if already inside the band, poke hardware immediately so a +; missed top IRQ (or mid-band offset change) cannot leave aliens at BXR=0. +.proc _pce_band_scroll_set + sta band_bxr + stx band_bxr+1 + lda band_enabled + beq done + lda band_phase + beq done + lda band_bxr + ldx band_bxr+1 + jmp write_bxr +done: rts +.endproc + +; void __fastcall__ pce_band_scroll_enable(unsigned int top_rcr, +; unsigned int bot_rcr); +; bot_rcr in A/X; top_rcr on soft stack. CR.RCR bit must be set by C. +.proc _pce_band_scroll_enable + sta band_bot_rcr + stx band_bot_rcr+1 + jsr popax + sta band_top_rcr + stx band_top_rcr+1 + lda #1 + sta band_enabled + stz band_phase + stz band_bxr + stz band_bxr+1 + lda #0 + tax + jsr write_bxr + lda band_top_rcr + ldx band_top_rcr+1 + jmp write_rcr +.endproc + +; void pce_band_scroll_disable(void); +.proc _pce_band_scroll_disable + stz band_enabled + lda #0 + tax + jsr write_rcr + lda #0 + tax + jmp write_bxr +.endproc + +; void pce_band_catchup(void); +; Call after VB-time VRAM work. If the top RCR was missed (phase still 0), +; force the scrolled BXR now so the formation does not sit at offset 0. +.proc _pce_band_catchup + lda band_enabled + beq done + lda band_phase + bne done + jmp band_apply_top +done: rts +.endproc + +.interruptor band_irq + +.proc band_irq + lda band_enabled + beq not_ours + lda vdc_flags + and #STATUS_RCR + bne do_rcr + lda vdc_flags + and #STATUS_VB + bne do_vb +not_ours: + clc + rts + +do_vb: + ; Re-arm at true vblank: HUD-safe BXR=0, wait for top. + stz band_phase + lda #0 + tax + jsr write_bxr + lda band_top_rcr + ldx band_top_rcr+1 + jsr write_rcr + clc + rts + +do_rcr: + lda band_phase + bne at_bot + jsr band_apply_top + sec + rts +at_bot: + jsr band_apply_bot + sec + rts +.endproc diff --git a/presets/pce/perftest.c b/presets/pce/perftest.c new file mode 100644 index 000000000..4ed76837d --- /dev/null +++ b/presets/pce/perftest.c @@ -0,0 +1,290 @@ +/* + * PC Engine graphics pipeline benchmark. + * + * Isolates vsync / SATB / BAT / put_tile / TIA / game-shaped workloads. + * After each scenario finishes, paints a bar chart: + * + * Columns 0..9 : OVER (brick) — vsync overruns (want 0) + * Columns 10..19 : BUSY (floor) — avg SATB-idle wait iters / 4 + * Columns 20..29 : SLACK (sky) — free loops until next VB >> 6 + * Column 31 : star — row marker + * + * Row 0 = legend. Rows 2+ = scenarios. Row 27 = live progress while running. + * I / RUN restarts. + * + * Build: scripts/build_pce_local.sh perftest [mame|geargrafx] + */ +//#resource "pcegfx.h" +//#resource "gfxtest_gfx.h" +//#link "pcegfx.c" +//#link "pcegfx_tia.s" + +#include +#include "pcegfx.h" +#include "gfxtest_gfx.h" + +#define TILE0 PCE_TILE_BASE +#define SPR0 PCE_SPR_BASE +#define TEST_FRAMES 30 + +typedef void (*work_fn)(void); + +typedef struct { + const char *name; + work_fn work; + byte use_busy; /* 1 = pce_wait_vsync, 0 = VB only */ + word over; + word busy_avg; + word slack; +} Scenario; + +static word bat_row[32]; +static unsigned char burst_buf[256]; +static word frame_i; +static byte done; +static byte scen; + +/* Exported so MAME/lua can peek progress: $22xx via map */ +unsigned char pce_perf_scen = 0; +unsigned char pce_perf_done = 0; + +static word slack_until_vb(void) { + word n = 0; + if (pce_vb_pending()) return 0; + while (!pce_vb_pending()) { + if (++n == 0) return 0xFFFF; + } + return n; +} + +static void work_none(void) {} + +static void work_satb15(void) { + byte i; + word a = PCE_SPR_PRI | PCE_SPR_PAL(0); + for (i = 0; i < 15; i++) + PCE_SPR_SET(i, (word)(PCE_SPR_X0 + i * 8), PCE_SPR_Y0 + 90, + PCE_SPR_PATTERN(i % 3), a); + pce_satb_update_n(15); +} + +static void work_satb64(void) { + byte i; + word a = PCE_SPR_PRI | PCE_SPR_PAL(0); + for (i = 0; i < 64; i++) + PCE_SPR_SET(i, (word)(PCE_SPR_X0 + (i & 15) * 12), + (word)(PCE_SPR_Y0 + (i >> 4) * 18), + PCE_SPR_PATTERN(i % 3), a); + pce_satb_update_n(64); +} + +static void work_bat1(void) { + byte i; + for (i = 0; i < 32; i++) + bat_row[i] = PCE_BAT(TILE0 + 2, 0); + pce_put_bat_row(0, (byte)(8 + (frame_i & 7)), bat_row, 32); +} + +static void work_bat4(void) { + byte r; + work_bat1(); + for (r = 1; r < 4; r++) + pce_put_bat_row(0, (byte)(8 + r), bat_row, 32); +} + +static void work_put32(void) { + byte x, y = (byte)(8 + (frame_i & 7)); + for (x = 0; x < 32; x++) + pce_put_tile(x, y, PCE_BAT(TILE0 + 3, 0)); +} + +static void work_tia64(void) { pce_vram_burst(0x1000, burst_buf, 64); } +static void work_tia256(void) { pce_vram_burst(0x1000, burst_buf, 256); } + +static void work_solar(void) { work_bat1(); work_satb15(); } + +static void work_chase(void) { + byte i; + word a = PCE_SPR_PRI | PCE_SPR_PAL(0); + static word cell[2]; + cell[0] = cell[1] = PCE_BAT(TILE0 + 2, 0); + for (i = 0; i < 3; i++) { + word addr = PCE_BAT_ADDR_XY((byte)(i * 4), (byte)(10 + i)); + pce_vram_burst(addr, cell, 4); + pce_vram_burst((word)(addr + 32), cell, 4); + } + for (i = 0; i < 4; i++) + PCE_SPR_SET(i, (word)(PCE_SPR_X0 + 50 + i * 20), PCE_SPR_Y0 + 140, + PCE_SPR_PATTERN(i % 3), a); + pce_satb_update_n(4); +} + +static void work_cpu(void) { + volatile word n = 0; + word i; + /* ~cheap CPU burn; 2k was enough to miss frames on 7.6MHz */ + for (i = 0; i < 800; i++) n += i; +} + +static Scenario scenarios[] = { + { "IDLE+BUSY", work_none, 1, 0, 0, 0 }, + { "IDLE VB", work_none, 0, 0, 0, 0 }, + { "SATB15", work_satb15,1, 0, 0, 0 }, + { "SATB64", work_satb64,1, 0, 0, 0 }, + { "BAT1", work_bat1, 1, 0, 0, 0 }, + { "BAT4", work_bat4, 1, 0, 0, 0 }, + { "PUT32", work_put32, 1, 0, 0, 0 }, + { "TIA64", work_tia64, 1, 0, 0, 0 }, + { "TIA256", work_tia256,1, 0, 0, 0 }, + { "SOLAR", work_solar, 1, 0, 0, 0 }, + { "CHASE", work_chase, 1, 0, 0, 0 }, + { "CPU2K", work_cpu, 1, 0, 0, 0 }, + { "SOLAR VB", work_solar, 0, 0, 0, 0 }, +}; +#define NSCENARIO (sizeof(scenarios) / sizeof(scenarios[0])) + +static void paint_progress(byte s, word f) { + byte x, filled; + word brick = PCE_BAT(TILE0 + 3, 0); + word blank = PCE_BAT(TILE0, 0); + /* scenario index in cols 0..NSCENARIO-1 */ + for (x = 0; x < 32; x++) + pce_put_tile(x, 27, x < s ? brick : blank); + /* frame fraction in row 26 */ + filled = (byte)((f * 32) / TEST_FRAMES); + for (x = 0; x < 32; x++) + pce_put_tile(x, 26, x < filled ? PCE_BAT(TILE0 + 2, 0) : blank); +} + +static void paint_chart(void) { + byte i, x; + word blank = PCE_BAT(TILE0, 0); + word sky = PCE_BAT(TILE0 + 1, 0); + word floor = PCE_BAT(TILE0 + 2, 0); + word brick = PCE_BAT(TILE0 + 3, 0); + word star = PCE_BAT(TILE0 + 4, 0); + + /* TIA tests may have clobbered tile data at $1000 — reload. */ + pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_satb_clear(); + pce_satb_update(); + + pce_fill_bat(0, 0, 32, 28, blank); + + for (x = 0; x < 10; x++) pce_put_tile(x, 0, brick); + for (x = 10; x < 20; x++) pce_put_tile(x, 0, floor); + for (x = 20; x < 30; x++) pce_put_tile(x, 0, sky); + pce_put_tile(31, 0, star); + + for (i = 0; i < NSCENARIO; i++) { + Scenario *s = &scenarios[i]; + byte y = (byte)(2 + i); + byte ow = s->over > 10 ? 10 : (byte)s->over; + byte bw = (byte)(s->busy_avg >> 2); + byte sw = (byte)(s->slack >> 6); + if (bw > 10) bw = 10; + if (sw > 10) sw = 10; + for (x = 0; x < 10; x++) + pce_put_tile(x, y, x < ow ? brick : blank); + for (x = 0; x < 10; x++) + pce_put_tile((byte)(10 + x), y, x < bw ? floor : blank); + for (x = 0; x < 10; x++) + pce_put_tile((byte)(20 + x), y, x < sw ? sky : blank); + pce_put_tile(31, y, star); + } +} + +static void run_one(Scenario *s) { + word over0 = pce_vsync_overruns; + word busy_sum = 0; + word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); + + for (frame_i = 0; frame_i < TEST_FRAMES; frame_i++) { + if (s->use_busy) + pce_wait_vsync(); + else + pce_wait_vsync_vb(); + + if (s->use_busy) + busy_sum += pce_busy_wait_iters; + + s->work(); + + PCE_SPR_SET(0, (word)(PCE_SPR_X0 + (frame_i * 3)), + (word)(PCE_SPR_Y0 + 40 + scen * 8), + PCE_SPR_PATTERN(0), attr); + /* Heartbeat sprite when the workload itself doesn't upload SATB */ + if (s->work == work_none || s->work == work_bat1 || s->work == work_bat4 || + s->work == work_put32 || s->work == work_tia64 || s->work == work_tia256 || + s->work == work_cpu) + pce_satb_update_n(1); + } + paint_progress((byte)(scen + 1), TEST_FRAMES); + + if (s->use_busy) pce_wait_vsync(); + else pce_wait_vsync_vb(); + s->work(); + s->slack = slack_until_vb(); + s->over = (word)(pce_vsync_overruns - over0); + s->busy_avg = s->use_busy ? (word)(busy_sum / TEST_FRAMES) : 0; +} + +static void setup(void) { + word bi; + pce_gfx_init(); + pce_disp_off(); + pce_load_palette(0, gfxtest_bg_pal, 16); + pce_load_palette(256, gfxtest_spr_pal, 16); + pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_load_sprites(SPR0, gfxtest_sprites, GFXTEST_NSPR); + for (bi = 0; bi < sizeof(burst_buf); bi++) + burst_buf[bi] = (unsigned char)bi; + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + 1, 0)); + pce_satb_clear(); + pce_satb_update(); + pce_disp_on(); +} + +int main(void) { + word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); + + joy_install(joy_static_stddrv); + setup(); + + for (;;) { + pce_perf_done = 0; + + for (frame_i = 0; frame_i < 30; frame_i++) { + pce_wait_vsync(); + PCE_SPR_SET(0, (word)(PCE_SPR_X0 + frame_i * 2), PCE_SPR_Y0 + 80, + PCE_SPR_PATTERN(0), attr); + pce_satb_update_n(1); + paint_progress(0, frame_i); + } + + pce_vsync_overruns = 0; + done = 0; + for (scen = 0; scen < NSCENARIO; scen++) { + pce_perf_scen = scen; + run_one(&scenarios[scen]); + } + + paint_chart(); + done = 1; + pce_perf_done = 1; + + for (;;) { + byte joy; + pce_wait_vsync(); + PCE_SPR_SET(0, (word)(PCE_SPR_X0 + ((frame_i++) & 127)), + PCE_SPR_Y0 + 200, PCE_SPR_PATTERN(1), attr); + pce_satb_update_n(1); + joy = joy_read(JOY_1); + if (JOY_BTN_I(joy) || JOY_RUN(joy)) + break; + } + while (JOY_BTN_I(joy_read(JOY_1)) || JOY_RUN(joy_read(JOY_1))) + pce_wait_vsync(); + } + return 0; +} diff --git a/presets/pce/solarian.c b/presets/pce/solarian.c new file mode 100644 index 000000000..2dfa7029f --- /dev/null +++ b/presets/pce/solarian.c @@ -0,0 +1,671 @@ +/* + * Solarian for PC Engine — a 1:1 gameplay port of + * presets/galaxian-scramble/shoot2.c (the "source of truth" Galaxian-hardware + * shoot-em-up), rendered with the pcegfx VDC/VCE tile+sprite SDK (no conio). + * + * All game math (attacker 8.8 fixed point, SINTBL, formation geometry, + * think/dive thresholds, wave timing) runs in the original Galaxian pixel + * space (0..255), exactly like shoot2.c. GX()/GY() convert that space to + * PC Engine screen/sprite coordinates only at the point something is drawn. + * + * Gfx: scripts/gen_pce_solarian_gfx.py (from presets/nes/shoot2.c TILESET). + * Controls: pad move, I or RUN = fire / start. + */ +//#resource "pcegfx.h" +//#resource "solarian_gfx.h" +//#link "pcegfx.c" +//#link "pcegfx_tia.s" + +#include +#include "pcegfx.h" +#include "solarian_gfx.h" + +#define TILE0 PCE_TILE_BASE +#define SPR0 PCE_SPR_BASE + +#define ENEMIES_PER_ROW 8 +#define ENEMY_ROWS 4 +#define MAX_IN_FORMATION (ENEMIES_PER_ROW * ENEMY_ROWS) +#define MAX_ATTACKERS 6 +#define MAX_MISSILES 8 +#define PLAYER_MISSILE 7 + +/* Exact shoot2.c formation geometry (Galaxian pixel space) */ +#define FORMATION_X0 18 +#define FORMATION_Y0 27 +#define FORMATION_XS 24 +#define FORMATION_YS 16 +#define GAL_HIT 16 /* shoot2 in_rect w/h */ +#define PLAYER_Y 232 /* shoot2 player_y (constant) */ +#define PLAYER_X0 112 /* shoot2 new_player_ship */ + +#define FLIPX 0x40 +#define FLIPY 0x80 +#define FLIPXY 0xc0 + +#define TILE_COLS 32 +#define TILE_ROWS 28 + +/* Galaxian space (0..255) -> PCE sprite/BAT space. X is 1:1 (both ~256px + * wide); Y is squeezed 256->224 so player_y=232 stays on the 224-line screen. + * (g*224)>>8 == (g*7)>>3 == ((g<<3)-g)>>3 — no runtime multiply/divide. */ +#define GAL_TO_PY(g) ((word)(((((word)(byte)(g) << 3) - (byte)(g)) >> 3))) +#define GX(g) ((word)(PCE_SPR_X0 + (byte)(g))) +#define GY(g) ((word)(PCE_SPR_Y0 + GAL_TO_PY(g))) +#define BGX(g) ((byte)((byte)(g) >> 3)) +#define BGY(g) ((byte)(GAL_TO_PY(g) >> 3)) + +typedef struct { byte shape; } FormationEnemy; +typedef struct { + byte findex; + byte shape; + word x, y; /* 8.8 fixed point, Galaxian pixel space */ + byte dir; + byte returning; +} AttackingEnemy; +typedef struct { + byte active; + word x, y; /* Galaxian pixel space */ + sbyte dy; +} Missile; + +FormationEnemy formation[MAX_IN_FORMATION]; +AttackingEnemy attackers[MAX_ATTACKERS]; +Missile missiles[MAX_MISSILES]; + +word formation_offset_x; +sbyte formation_direction; +byte current_row; +byte player_x; +byte player_exploding; +byte enemy_exploding; +word boom_x, boom_y; +byte enemies_left; +word player_score; +word framecount; +byte lives; + +/* Galaxian shoot2 DIR_TO_CODE — dive toward +Y (player at bottom) */ +static const byte DIR_TO_CODE[32] = { + 0, 1, 2, 3, 4, 5, 6, 6, + 6|FLIPXY, 6|FLIPXY, 5|FLIPXY, 4|FLIPXY, 3|FLIPXY, 2|FLIPXY, 1|FLIPXY, 0|FLIPXY, + 0|FLIPX, 1|FLIPX, 2|FLIPX, 3|FLIPX, 4|FLIPX, 5|FLIPX, 6|FLIPX, 6|FLIPX, + 6|FLIPY, 6|FLIPY, 5|FLIPY, 4|FLIPY, 3|FLIPY, 2|FLIPY, 1|FLIPY, 0|FLIPY, +}; + +/* Exact Galaxian shoot2 SINTBL (unmultiplied) */ +static const byte SINTBL[32] = { + 0, 25, 49, 71, 90, 106, 117, 125, + 127, 125, 117, 106, 90, 71, 49, 25, + 0, (byte)-25, (byte)-49, (byte)-71, (byte)-90, (byte)-106, (byte)-117, (byte)-125, + (byte)-127, (byte)-125, (byte)-117, (byte)-106, (byte)-90, (byte)-71, (byte)-49, (byte)-25, +}; + +static word lfsr = 1; + +word rand16(void) { + byte lsb = (byte)(lfsr & 1); + lfsr >>= 1; + if (lsb) lfsr ^= 0xB400; + return lfsr; +} + +sbyte isin(byte dir) { return (sbyte)SINTBL[dir & 31]; } +sbyte icos(byte dir) { return isin((byte)(dir + 8)); } + +#define PIX(fp) ((byte)((fp) >> 8)) + +/* ---- tile/text helpers ------------------------------------------------ */ + +void poke_tile(byte x, byte y, word code) { + if (x >= TILE_COLS || y >= TILE_ROWS) return; + pce_put_tile(x, y, PCE_BAT(TILE0 + code, 0)); +} + +byte font_code(char ch) { + if (ch >= '0' && ch <= '9') return (byte)(T_DIGIT + (ch - '0')); + if (ch >= 'a' && ch <= 'z') ch = (char)(ch - 32); + if (ch >= 'A' && ch <= 'Z') return (byte)(T_LETTER + (ch - 'A')); + return T_BLANK; +} + +void put_char(byte x, byte y, char ch) { poke_tile(x, y, font_code(ch)); } + +void put_string(byte x, byte y, const char* s) { + while (*s) put_char(x++, y, *s++); +} + +void put_digit(byte x, byte y, byte d) { poke_tile(x, y, (word)(T_DIGIT + (d & 15))); } + +word bcd_add(word a, word b) { + word r = 0; + byte i, carry = 0; + for (i = 0; i < 4; i++) { + byte n = (byte)((a & 15) + (b & 15) + carry); + if (n > 9) { n = (byte)(n - 10); carry = 1; } + else carry = 0; + r |= (word)n << (i * 4); + a >>= 4; + b >>= 4; + } + return r; +} + +void clrscr(void) { + pce_fill_bat(0, 0, TILE_COLS, TILE_ROWS, PCE_BAT(TILE0 + T_BLANK, 0)); + pce_satb_clear(); + pce_satb_update(); +} + +void draw_score(void) { + byte i; + word s = player_score; + put_string(1, 0, "SCORE"); + for (i = 0; i < 4; i++) { + put_digit((byte)(9 - i), 0, (byte)(s & 0xf)); + s >>= 4; + } + put_string(14, 0, "LIVES"); + put_digit(20, 0, lives); + /* Lag digit: vsync overruns (0 = locked 60Hz). */ + put_digit(30, 0, (byte)(pce_vsync_overruns & 15)); +} + +void add_score(word bcd) { + player_score = bcd_add(player_score, bcd); + draw_score(); +} + +void seed_stars(void) { + byte i; + for (i = 0; i < 20; i++) { + byte x = (byte)(rand16() & 31); + byte y = (byte)(2 + (rand16() % 25)); + poke_tile(x, y, (rand16() & 1) ? T_STAR1 : T_STAR2); + } +} + +/* ---- formation (BAT once + BXR band scroll + CHR flap) -------------------- */ + +byte form_spark; + +byte form_tile_x(byte col) { + return (byte)((FORMATION_X0 >> 3) + col * 3); +} + +byte form_tile_y(byte row) { + return BGY((byte)(FORMATION_Y0 + row * FORMATION_YS)); +} + +void form_set_frame(byte spark) { + const unsigned char *src = + spark ? &solarian_tiles[T_FORM_B * 32] + : &solarian_tiles[T_FORM_A * 32]; + form_spark = spark; + pce_load_tiles(TILE0 + T_FORM_A, src, T_FORM_NTILE); +} + +void draw_formation_slot(byte fi) { + byte col = (byte)(fi & (ENEMIES_PER_ROW - 1)); + byte row = (byte)(fi >> 3); + byte tx = form_tile_x(col); + byte ty = form_tile_y(row); + if (tx >= TILE_COLS - 2) return; + if (formation[fi].shape) { + poke_tile(tx, ty, T_FORM_A); + poke_tile((byte)(tx + 1), ty, (word)(T_FORM_A + 1)); + poke_tile((byte)(tx + 2), ty, (word)(T_FORM_A + 2)); + } else { + poke_tile(tx, ty, T_BLANK); + poke_tile((byte)(tx + 1), ty, T_BLANK); + poke_tile((byte)(tx + 2), ty, T_BLANK); + } +} + +void redraw_formation(void) { + byte i; + for (i = 0; i < MAX_IN_FORMATION; i++) + draw_formation_slot(i); +} + +void setup_formation(void) { + byte i; + for (i = 0; i < MAX_IN_FORMATION; i++) formation[i].shape = 1; + for (i = 0; i < MAX_ATTACKERS; i++) attackers[i].findex = 0; + for (i = 0; i < MAX_MISSILES; i++) missiles[i].active = 0; + enemies_left = MAX_IN_FORMATION; + formation_offset_x = 0; + formation_direction = 1; + current_row = 0; + form_spark = 0; + pce_band_set_x(0); +} + +byte get_attacker_x(byte fi) { + byte col = (byte)(fi & (ENEMIES_PER_ROW - 1)); + return (byte)(FORMATION_X0 + formation_offset_x + col * FORMATION_XS); +} + +byte get_attacker_y(byte fi) { + byte row = (byte)(fi >> 3); + return (byte)(FORMATION_Y0 + row * FORMATION_YS); +} + +/* Advance scroll ~1px every ENEMY_ROWS frames (same pace as old BAT redraw). */ +void update_formation_motion(void) { + byte spark; + if (++current_row >= ENEMY_ROWS) { + current_row = 0; + formation_offset_x = (word)(formation_offset_x + formation_direction); + if (formation_offset_x == 40) formation_direction = -1; + else if (formation_offset_x == 0) formation_direction = 1; + pce_band_set_x(formation_offset_x); + } + spark = (byte)((framecount >> 4) & 1); + if (spark != form_spark) + form_set_frame(spark); +} + +void enable_formation_scroll(void) { + byte top = (byte)GAL_TO_PY(FORMATION_Y0); + byte bot = (byte)(GAL_TO_PY((byte)(FORMATION_Y0 + ENEMY_ROWS * FORMATION_YS)) + 8); + /* RCR applies BXR on the *next* line; start ~8 lines early so the first + * alien row is fully inside the scrolled band (was ~2, looked 6 late). */ + if (top > 8) top = (byte)(top - 8); + else top = 0; + pce_band_enable(top, bot); + pce_band_set_x(formation_offset_x); +} + +/* ---- attackers ---------------------------------------------------------- */ + +/* shoot2: dock when ydist==0 (byte wrap); else aim and y += 128 */ +void return_attacker(AttackingEnemy* a) { + byte fi = (byte)(a->findex - 1); + byte destx = get_attacker_x(fi); + byte desty = get_attacker_y(fi); + byte ydist = (byte)(desty - PIX(a->y)); + if (ydist == 0) { + formation[fi].shape = a->shape; + a->findex = 0; + draw_formation_slot(fi); + } else { + a->dir = (byte)((ydist + 16) & 31); + a->x = (word)destx << 8; + a->y += 128; + } +} + +/* shoot2: x += isin*2, y += icos*2; head home when Y wraps to 0 */ +void fly_attacker(AttackingEnemy* a) { + a->x += (word)(isin(a->dir) * 2); + a->y += (word)(icos(a->dir) * 2); + if (PIX(a->y) == 0) a->returning = 1; +} + +void move_attackers(void) { + byte i; + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + if (!a->findex) continue; + if (a->returning) return_attacker(a); + else fly_attacker(a); + } +} + +/* shoot2: y<128 or exploding -> turn on x<112; else fire if slot free */ +void think_attackers(void) { + byte i; + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + byte x, y; + if (!a->findex) continue; + x = PIX(a->x); + y = PIX(a->y); + if (y < 128 || player_exploding) { + if (x < 112) a->dir++; + else a->dir--; + } else if (!missiles[i].active) { + missiles[i].active = 1; + missiles[i].x = (word)(x + 8); + missiles[i].y = (word)y; + missiles[i].dy = 2; + } + } +} + +void formation_to_attacker(byte fi) { + byte i; + if (fi >= MAX_IN_FORMATION || !formation[fi].shape) return; + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + if (a->findex == 0) { + a->x = (word)get_attacker_x(fi) << 8; + a->y = (word)get_attacker_y(fi) << 8; + a->shape = formation[fi].shape; + a->findex = (byte)(fi + 1); + a->dir = 0; + a->returning = 0; + formation[fi].shape = 0; + draw_formation_slot(fi); + break; + } + } +} + +void new_attack_wave(void) { + byte i = (byte)(rand16() & (MAX_IN_FORMATION - 1)); + byte j; + for (j = 0; j < MAX_IN_FORMATION; j++) { + i = (byte)((i + 1) & (MAX_IN_FORMATION - 1)); + if (formation[i].shape) { + formation_to_attacker(i); + formation_to_attacker((byte)(i + 1)); + formation_to_attacker((byte)(i + ENEMIES_PER_ROW)); + formation_to_attacker((byte)(i + ENEMIES_PER_ROW + 1)); + break; + } + } +} + +/* Put divers back in their slots and redraw formation (restart wave). */ +void recall_attackers(void) { + byte i; + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + if (a->findex) { + formation[(byte)(a->findex - 1)].shape = a->shape; + a->findex = 0; + a->returning = 0; + } + } + redraw_formation(); +} + +/* ---- missiles ------------------------------------------------------------ */ + +/* shoot2 after un-inverting HW Y: player dy=-4, enemy dy=+2. + * All missiles are sprites (no BG erase/redraw — that was a major stall). */ +void move_missiles(void) { + byte i; + for (i = 0; i < MAX_MISSILES; i++) { + if (!missiles[i].active) continue; + if (missiles[i].dy < 0) { + byte step = (byte)(-missiles[i].dy); + if (missiles[i].y < step) { missiles[i].active = 0; continue; } + missiles[i].y -= step; + } else if (missiles[i].dy > 0) { + missiles[i].y += (byte)missiles[i].dy; + if (missiles[i].y > 235) missiles[i].active = 0; + } + } +} + +void hide_player_missile(void) { missiles[PLAYER_MISSILE].active = 0; } + +void clear_all_missiles(void) { + byte i; + for (i = 0; i < MAX_MISSILES; i++) missiles[i].active = 0; +} + +/* ---- player --------------------------------------------------------------- */ + +void new_player_ship(void) { + player_exploding = 0; + player_x = PLAYER_X0; + clear_all_missiles(); +} + +void move_player(void) { + byte joy = joy_read(JOY_1); + if (JOY_LEFT(joy) && player_x > 16) player_x--; + if (JOY_RIGHT(joy) && player_x < 224) player_x++; + if ((JOY_BTN_I(joy) || JOY_RUN(joy)) && !missiles[PLAYER_MISSILE].active) { + missiles[PLAYER_MISSILE].active = 1; + missiles[PLAYER_MISSILE].x = player_x; + missiles[PLAYER_MISSILE].y = (word)(PLAYER_Y - 8); + missiles[PLAYER_MISSILE].dy = -4; + } +} + +/* Galaxian shoot2: unsigned wrap — (x-x0) < w as unsigned */ +char in_rect(byte x, byte y, byte x0, byte y0, byte w, byte h) { + return ((byte)(x - x0) < w && (byte)(y - y0) < h); +} + +void blowup_at(word x, word y) { + boom_x = x; + boom_y = y; + enemy_exploding = 1; +} + +void animate_boom(void) { + if (!enemy_exploding) return; + enemy_exploding++; + if (enemy_exploding > 8) enemy_exploding = 0; +} + +void does_player_shoot_formation(void) { + byte mx, my, column, localx, index; + sbyte row; + byte xoffset; + if (!missiles[PLAYER_MISSILE].active) return; + mx = (byte)missiles[PLAYER_MISSILE].x; + my = (byte)missiles[PLAYER_MISSILE].y; + /* FORMATION_YS == 16 */ + row = (sbyte)((byte)(my - FORMATION_Y0) >> 4); + if (row < 0 || row >= ENEMY_ROWS) return; + xoffset = (byte)(mx - FORMATION_X0 - (byte)formation_offset_x); + column = (byte)(xoffset / FORMATION_XS); + localx = (byte)(xoffset - column * FORMATION_XS); + if (column < ENEMIES_PER_ROW && localx < GAL_HIT) { + index = (byte)(column + (byte)row * ENEMIES_PER_ROW); + if (formation[index].shape) { + formation[index].shape = 0; + enemies_left--; + draw_formation_slot(index); + blowup_at(GX(get_attacker_x(index)), GY(get_attacker_y(index))); + hide_player_missile(); + add_score(0x0002); + } + } +} + +void does_player_shoot_attacker(void) { + byte i, mx, my; + if (!missiles[PLAYER_MISSILE].active) return; + mx = (byte)missiles[PLAYER_MISSILE].x; + my = (byte)missiles[PLAYER_MISSILE].y; + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + if (a->findex && in_rect(mx, my, PIX(a->x), PIX(a->y), GAL_HIT, GAL_HIT)) { + blowup_at(GX(PIX(a->x)), GY(PIX(a->y))); + a->findex = 0; + enemies_left--; + hide_player_missile(); + add_score(0x0005); + break; + } + } +} + +/* shoot2: enemy missile slots only; 16x16 in Galaxian space */ +void does_missile_hit_player(void) { + byte i; + if (player_exploding) return; + for (i = 0; i < MAX_ATTACKERS; i++) { + if (missiles[i].active && + in_rect((byte)missiles[i].x, (byte)missiles[i].y, player_x, PLAYER_Y, GAL_HIT, GAL_HIT)) { + player_exploding = 1; + clear_all_missiles(); + break; + } + } +} + +/* ---- sprite flush (once per frame) ---------------------------------------- */ +/* slots: 0 ship, 1-6 divers, 7 player bullet, 8 boom, 9-14 enemy bullets */ + +#define SPR_SLOTS 15 + +static void update_sprites(void) { + byte i; + word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); + + /* Park unused slots with Y=0; write actives via macros (no call overhead). */ + for (i = 0; i < SPR_SLOTS; i++) + PCE_SPR_HIDE(i); + + if (player_exploding) { + PCE_SPR_SET(0, GX(player_x), GY(PLAYER_Y), + PCE_SPR_PATTERN((player_exploding & 1) ? S_BOOM1 : S_BOOM2), attr); + } else { + PCE_SPR_SET(0, GX(player_x), GY(PLAYER_Y), PCE_SPR_PATTERN(S_PLAYER), attr); + } + + for (i = 0; i < MAX_ATTACKERS; i++) { + AttackingEnemy* a = &attackers[i]; + if (a->findex) { + byte code = DIR_TO_CODE[a->dir & 31]; + word aattr = attr; + if (code & FLIPX) aattr |= PCE_SPR_HFLIP; + if (code & FLIPY) aattr |= PCE_SPR_VFLIP; + PCE_SPR_SET((byte)(1 + i), GX(PIX(a->x)), GY(PIX(a->y)), + PCE_SPR_PATTERN(S_ATK0 + (code & 7)), aattr); + } + } + + if (missiles[PLAYER_MISSILE].active) + PCE_SPR_SET(7, GX(missiles[PLAYER_MISSILE].x), GY(missiles[PLAYER_MISSILE].y), + PCE_SPR_PATTERN(S_BULLET), attr); + + if (enemy_exploding) + PCE_SPR_SET(8, boom_x, boom_y, + PCE_SPR_PATTERN((enemy_exploding & 1) ? S_BOOM1 : S_BOOM2), attr); + + for (i = 0; i < MAX_ATTACKERS; i++) { + if (!missiles[i].active) continue; + PCE_SPR_SET((byte)(9 + i), + GX(missiles[i].x), GY(missiles[i].y), + PCE_SPR_PATTERN(S_BULLET), attr); + } + + pce_satb_update_n(SPR_SLOTS); +} + +/* ---- setup / rounds -------------------------------------------------------- */ + +static void setup_gfx(void) { + pce_gfx_init(); + pce_disp_off(); + pce_load_palette(0, solarian_bg_pal, 16); + pce_load_palette(256, solarian_spr_pal, 16); + pce_load_tiles(TILE0, solarian_tiles, SOLARIAN_NTILE); + pce_load_sprites(SPR0, solarian_sprites, SOLARIAN_NSPR); + pce_satb_clear(); + pce_satb_update(); + pce_disp_on(); +} + +void play_round(void) { + byte end_timer = 255; + + player_score = 0; + lives = 3; + clrscr(); + seed_stars(); + draw_score(); + + setup_formation(); + enemy_exploding = 0; + framecount = 0; + pce_vsync_overruns = 0; + redraw_formation(); + enable_formation_scroll(); + new_player_ship(); + + while (end_timer) { + /* Post-DMA vblank: CHR flap / SATB. Scroll is RCR-driven. */ + pce_wait_vsync(); + update_formation_motion(); /* set_x first — updates HW BXR if already in-band */ + update_sprites(); + if ((framecount & 31) == 0) + put_digit(30, 0, (byte)(pce_vsync_overruns & 15)); + + framecount++; + + if (player_exploding) { + if ((framecount & 7) == 0) { + player_exploding++; + if (player_exploding > 32) { + lives--; + draw_score(); + if (lives && enemies_left) { + recall_attackers(); + new_player_ship(); + } else { + player_exploding = 0; + end_timer = 1; + } + } + } + } else { + if ((framecount & 0x7f) == 0 && enemies_left > 8) + new_attack_wave(); + move_player(); + does_missile_hit_player(); + } + + if ((framecount & 3) == 0) animate_boom(); + move_attackers(); + move_missiles(); + does_player_shoot_formation(); + does_player_shoot_attacker(); + if ((framecount & 0xf) == 0) think_attackers(); + + if (!enemies_left) end_timer--; + if (!lives && !player_exploding) end_timer--; + } + + pce_band_disable(); + pce_satb_clear(); + pce_satb_update(); + put_string(11, 14, "GAME OVER"); + { + byte t = 120; + while (t--) pce_wait_vsync(); + } +} + +#ifndef PCE_PERF_BENCH +static byte wait_for_start(void) { + byte joy; + do { + pce_wait_vsync(); + joy = joy_read(JOY_1); + } while (!(JOY_BTN_I(joy) || JOY_RUN(joy))); + do { + pce_wait_vsync(); + joy = joy_read(JOY_1); + } while (JOY_BTN_I(joy) || JOY_RUN(joy)); + return joy; +} +#endif + +int main(void) { + joy_install(joy_static_stddrv); + setup_gfx(); + + while (1) { +#ifndef PCE_PERF_BENCH + clrscr(); + put_string(10, 8, "SOLARIAN"); + put_string(3, 10, "GALAXIAN SCRAMBLE PORT"); + put_string(9, 14, "PRESS START"); + put_string(8, 16, "OR FIRE BUTTON"); + wait_for_start(); +#endif + play_round(); + } + return 0; +} diff --git a/presets/pce/solarian_gfx.h b/presets/pce/solarian_gfx.h new file mode 100644 index 000000000..8b98dde58 --- /dev/null +++ b/presets/pce/solarian_gfx.h @@ -0,0 +1,224 @@ +/* Auto-generated by scripts/gen_pce_solarian_gfx.py — do not edit */ +#ifndef SOLARIAN_GFX_H +#define SOLARIAN_GFX_H + +#define SOLARIAN_NTILE 46 +#define SOLARIAN_NSPR 12 + +/* BG tiles (8x8, PCE 4bpp) */ +#define T_BLANK 0 +#define T_FORM_A 1 /* live formation slots (3 tiles) */ +#define T_FORM_B 4 /* flap frame B source */ +#define T_FORM_NTILE 3 +#define T_BULLET_T 7 +#define T_STAR1 8 +#define T_STAR2 9 +#define T_DIGIT 10 /* +0..9 */ +#define T_LETTER 20 /* +0..25 = A..Z */ + +/* Sprites (16x16, PCE 4bpp) */ +#define S_PLAYER 0 +#define S_ATK0 1 /* +0..6 = dive angle frames */ +#define S_BOOM1 8 +#define S_BOOM2 9 +#define S_BULLET 10 +#define S_FORM 11 + +const unsigned char solarian_tiles[1472] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x04, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0x06, 0xF9, 0x51, 0xF8, 0x04, 0xF8, 0x02, 0x70, 0x89, 0x70, 0x04, 0x20, 0x02, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x06, 0xD9, 0x01, 0xF8, 0x50, 0xF8, 0x06, 0xF8, 0x01, 0x70, 0x88, 0x70, 0x04, 0x20, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x00, 0x78, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x0E, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x00, 0x0E, 0x00, 0x3C, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7E, 0x00, 0x0E, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xF8, 0x00, 0xEC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xEC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xC6, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xCE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0x7C, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x6C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xC6, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFE, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned char solarian_sprites[1536] = { + 0x40, 0x01, 0x40, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x44, 0x11, 0x44, 0x11, + 0x44, 0x11, 0x34, 0x16, 0x3C, 0x1E, 0x54, 0x15, 0x04, 0x10, 0x04, 0x10, 0x04, 0x10, 0x04, 0x10, + 0xC0, 0x01, 0xC0, 0x01, 0x20, 0x02, 0xF0, 0x07, 0xC0, 0x01, 0xC2, 0x21, 0xC2, 0x21, 0xEA, 0x2B, + 0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, 0xDE, 0x3D, 0xEE, 0x3B, 0x1E, 0x3C, 0x0A, 0x28, 0x0A, 0x28, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x10, 0x04, 0x60, 0x03, 0xE0, 0x03, 0xE0, 0x0F, + 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x10, 0x04, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00, + 0x06, 0x30, 0x20, 0x02, 0x10, 0x04, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x03, 0xE0, 0x03, 0xE0, 0x03, + 0xE0, 0x03, 0xC0, 0x07, 0xC0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x20, 0x00, 0x11, 0x40, 0x0C, + 0x10, 0x00, 0x0C, 0x20, 0x02, 0x1C, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x03, 0xE0, 0x03, 0xE0, 0x03, + 0xE0, 0x03, 0xC0, 0x07, 0xC0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x20, 0x00, 0x11, 0x40, 0x0C, + 0x10, 0x00, 0x0C, 0x20, 0x02, 0x1C, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x04, 0x01, 0xCC, 0x01, 0xF0, 0x03, 0xE0, 0x03, + 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x11, 0x04, 0x08, 0x0C, 0x04, 0x00, 0x01, 0x40, 0x20, + 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0xF0, 0x00, 0xFC, 0x01, + 0xFC, 0x03, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x04, 0x20, 0x02, 0x00, 0x11, 0x40, 0x08, 0x04, 0x04, + 0x2C, 0x04, 0x00, 0x00, 0x20, 0x00, 0x18, 0x00, 0x80, 0x00, 0x40, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x34, 0x00, 0xE0, 0x00, 0xE0, 0x03, 0xF0, 0x07, + 0xFA, 0x07, 0xE4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x88, 0x10, 0x94, 0x10, 0x00, 0x08, 0x40, 0x04, 0x00, 0x00, + 0x2A, 0x00, 0x04, 0x00, 0x80, 0x02, 0x40, 0x02, 0x20, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0xE0, 0x01, 0xE0, 0x07, + 0xC0, 0x0F, 0xE0, 0x07, 0xE0, 0x01, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x88, 0x08, 0x94, 0x04, 0x00, 0x02, 0x40, 0x00, + 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x94, 0x04, 0x88, 0x08, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x90, 0x04, 0xE0, 0x03, 0x90, 0x06, 0xD0, 0x05, + 0xF0, 0x05, 0x20, 0x06, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x30, 0x06, 0x10, 0x04, 0x00, 0x00, 0x0C, 0x18, + 0x0C, 0x18, 0x10, 0x00, 0x18, 0x08, 0xC8, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x40, 0x04, 0x08, 0x12, 0x91, 0x0C, 0xA2, 0x42, 0x04, 0x30, 0x80, 0x00, 0xCC, 0x19, + 0xC4, 0x11, 0x10, 0x04, 0x1A, 0x0C, 0x80, 0x00, 0x20, 0x21, 0x10, 0x46, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0A, 0x00, 0x00, 0x30, 0x06, 0x08, 0x08, 0x00, 0x00, + 0x10, 0x04, 0x04, 0x10, 0xA0, 0x02, 0x98, 0x0C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0xE4, 0x13, 0xE0, 0x03, 0xE0, 0x03, + 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x44, 0x11, 0x10, 0x04, 0x08, 0x08, + 0x24, 0x12, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const unsigned short solarian_bg_pal[16] = { 0x000, 0x1FF, 0x1C7, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short solarian_spr_pal[16] = { 0x000, 0x1FF, 0x0F8, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; + +#endif diff --git a/src/platform/pce.ts b/src/platform/pce.ts index 6a45268e4..9a9e58929 100644 --- a/src/platform/pce.ts +++ b/src/platform/pce.ts @@ -2,6 +2,10 @@ import { DisasmLine, Platform, Preset, getToolForFilename_6502 } from "../common import { Keys, PLATFORMS, RasterVideo } from "../common/emu"; const PCE_PRESETS = [ + { id: 'gfxtest.c', name: 'Graphics Test (tiles/sprites)' }, + { id: 'perftest.c', name: 'Graphics Pipeline Benchmark' }, + { id: 'solarian.c', name: 'Solarian' }, + { id: 'chase.c', name: 'Chase' }, { id: 'test_conio.c', name: 'Hello World (conio)' }, { id: 'siegegame.c', name: 'Siege Game (conio)' }, { id: 'hello.wiz', name: 'Hello World (Wiz)' }, From 7c0a7fc9abb151f55fce24be7cadac2f21b30c10 Mon Sep 17 00:00:00 2001 From: MikeDX Date: Sun, 2 Aug 2026 19:26:54 +0100 Subject: [PATCH 2/2] Enhance graphics handling for PC Engine Chase game - Updated chase_gfx.h to include additional tile and sprite definitions, increasing the number of tiles and sprites. - Modified chase.c to improve character and string rendering with palette support. - Introduced new functions for loading level palettes and handling tile drawing with palette options. - Refactored graphics loading functions to utilize planar tile formats for better compatibility with the PC Engine's graphics system. - Adjusted sprite handling to support multiple palettes for different actor types, enhancing visual fidelity. --- presets/pce/chase.c | 256 +++++++++++++-- presets/pce/chase_gfx.h | 638 ++++++++++++++++++++++++++++--------- presets/pce/gfxtest.c | 2 +- presets/pce/gfxtest_gfx.h | 77 ++--- presets/pce/pcegfx.c | 120 +++++-- presets/pce/pcegfx.h | 12 +- presets/pce/pcegfx_tia.s | 75 ++++- presets/pce/perftest.c | 4 +- presets/pce/solarian.c | 4 +- presets/pce/solarian_gfx.h | 386 +++++++++++----------- 10 files changed, 1121 insertions(+), 453 deletions(-) diff --git a/presets/pce/chase.c b/presets/pce/chase.c index cb65c74a1..29351d065 100644 --- a/presets/pce/chase.c +++ b/presets/pce/chase.c @@ -21,6 +21,8 @@ #define TILE0 PCE_TILE_BASE #define SPR0 PCE_SPR_BASE +void load_level_palette(byte li); + #define MAP_W 16 #define MAP_H 13 #define MAP_Y0 1 /* tile-rows above map[0] (HUD) */ @@ -175,16 +177,24 @@ byte font_code(char ch) { return TILE_EMPTY; } +void put_char_pal(byte x, byte y, char ch, byte pal) { + pce_put_tile(x, y, PCE_BAT(TILE0 + font_code(ch), pal)); +} + void put_char(byte x, byte y, char ch) { - pce_put_tile(x, y, PCE_BAT(TILE0 + font_code(ch), 0)); + put_char_pal(x, y, ch, PAL_HUD); +} + +void put_string_pal(byte x, byte y, const char* s, byte pal) { + while (*s) put_char_pal(x++, y, *s++, pal); } void put_string(byte x, byte y, const char* s) { - while (*s) put_char(x++, y, *s++); + put_string_pal(x, y, s, PAL_HUD); } void put_digit(byte x, byte y, byte d) { - pce_put_tile(x, y, PCE_BAT(TILE0 + TILE_DIGIT + (d % 10), 0)); + pce_put_tile(x, y, PCE_BAT(TILE0 + TILE_DIGIT + (d % 10), PAL_HUD)); } void hide_all_sprites(void) { @@ -194,16 +204,16 @@ void hide_all_sprites(void) { pce_satb_update_n(ACTORS_MAX); } -void set_cell_tiles(byte mx, byte my, byte tl, byte tr, byte bl, byte br) { +void set_cell_tiles(byte mx, byte my, byte tl, byte tr, byte bl, byte br, byte pal) { byte sx = (byte)(mx << 1); byte sy = (byte)((byte)(MAP_Y0 + my) << 1); static word row[2]; word addr = PCE_BAT_ADDR_XY(sx, sy); - row[0] = PCE_BAT(TILE0 + tl, 0); - row[1] = PCE_BAT(TILE0 + tr, 0); + row[0] = PCE_BAT(TILE0 + tl, pal); + row[1] = PCE_BAT(TILE0 + tr, pal); pce_vram_burst(addr, row, 4); - row[0] = PCE_BAT(TILE0 + bl, 0); - row[1] = PCE_BAT(TILE0 + br, 0); + row[0] = PCE_BAT(TILE0 + bl, pal); + row[1] = PCE_BAT(TILE0 + br, pal); pce_vram_burst((word)(addr + PCE_BAT_W), row, 4); } @@ -216,19 +226,22 @@ void gem_set_frame(byte spark) { spark ? &chase_tiles[TILE_GEM1_TL * 32] : &chase_tiles[TILE_GEM0_TL * 32]; gem_spark = spark; - pce_load_tiles(TILE0 + TILE_GEM0_TL, src, 4); + pce_load_tiles_planar(TILE0 + TILE_GEM0_TL, src, 4); } void draw_cell(byte x, byte y) { byte t = map_at(x, y); + /* Alternate wall subpals 1/3 like NES attribute checkerboard */ + byte wall_pal = (byte)(((x ^ y) & 1) ? PAL_WALLB : PAL_WALL); if (t == T_WALL) - set_cell_tiles(x, y, TILE_WALL_TL, TILE_WALL_TR, TILE_WALL_BL, TILE_WALL_BR); + set_cell_tiles(x, y, TILE_WALL_TL, TILE_WALL_TR, TILE_WALL_BL, TILE_WALL_BR, wall_pal); else if (t == T_ITEM) - set_cell_tiles(x, y, TILE_GEM0_TL, TILE_GEM0_TR, TILE_GEM0_BL, TILE_GEM0_BR); + /* NES: floor + gems share attr pal 2 (black, floor bg, 2 gem colours) */ + set_cell_tiles(x, y, TILE_GEM0_TL, TILE_GEM0_TR, TILE_GEM0_BL, TILE_GEM0_BR, PAL_FLOOR); else if (t == T_FLOOR) - set_cell_tiles(x, y, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR); + set_cell_tiles(x, y, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR, TILE_FLOOR, PAL_FLOOR); else - set_cell_tiles(x, y, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY); + set_cell_tiles(x, y, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY, TILE_EMPTY, PAL_HUD); } void draw_hud(void) { @@ -300,7 +313,10 @@ void load_level(byte li) { gem_n = 0; game_level = li; gem_set_frame(0); - pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + pce_disp_off(); + load_level_palette(li); + __asm__("sei"); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, PAL_HUD)); hide_all_sprites(); for (y = 0; y < MAP_H; y++) { row = levels[li][y]; @@ -345,12 +361,13 @@ void load_level(byte li) { for (y = 0; y < MAP_H; y++) for (x = 0; x < MAP_W; x++) draw_cell(x, y); + __asm__("cli"); spawn_wait = (byte)(actor_n << 4); + pce_disp_on(); } void draw_actors(void) { byte i; - word attr = PCE_SPR_PRI | PCE_SPR_PAL(0); for (i = 0; i < ACTORS_MAX; i++) PCE_SPR_HIDE(i); for (i = 0; i < actor_n; i++) { @@ -358,12 +375,15 @@ void draw_actors(void) { word px = (word)(PCE_SPR_X0 + (a->x >> FP_BITS)); word py = (word)(PCE_SPR_Y0 + (MAP_Y0 * TILE_SIZE) + (a->y >> FP_BITS)); byte shape; + word attr; if (a->wait && (a->wait >= 16 || (a->wait & 2))) continue; + /* NES: player pal 0, enemy1/2/3 → spr pal 1/2/3 */ + attr = PCE_SPR_PRI | PCE_SPR_PAL(a->kind & 3); if (a->kind == 0) shape = (frame_cnt & 8) ? SPR_PLAYER2 : SPR_PLAYER; else - shape = SPR_ENEMY; + shape = (frame_cnt & 8) ? SPR_ENEMY2 : SPR_ENEMY; PCE_SPR_SET(i, px, py, PCE_SPR_PATTERN(shape), attr); } pce_satb_update_n(ACTORS_MAX); @@ -463,46 +483,222 @@ void wait_for_fire(void) { while (joy_fire) { wait_frame(); read_controls(); } } +void load_level_palette(byte li) { + /* NES 4×4 pack → PCE BG pals 0..3 */ + pce_load_nes_pal(0, chase_level_pal[li]); +} + void setup_gfx(void) { pce_gfx_init(); pce_disp_off(); - pce_load_palette(0, chase_bg_pal, 16); - pce_load_palette(256, chase_spr_pal, 16); - pce_load_tiles(TILE0, chase_tiles, CHASE_NTILE); + pce_load_nes_pal(0, chase_bg_pal); + pce_load_nes_pal(256, chase_spr_pal); + pce_load_tiles_planar(TILE0, chase_tiles, CHASE_NTILE); pce_load_sprites(SPR0, chase_sprites, CHASE_NSPR); pce_satb_clear(); pce_satb_update(); pce_disp_on(); } +void draw_title_bat_at(int y_off_tiles) { + byte dy; + static word blank_row[32]; + static byte blank_init; + if (!blank_init) { + byte x; + for (x = 0; x < 32; x++) + blank_row[x] = PCE_BAT(TILE0 + TILE_EMPTY, 0); + blank_init = 1; + } + for (dy = 0; dy < 28; dy++) { + int src = (int)dy - y_off_tiles; + if (src >= 0 && src < (int)CHASE_TITLE_H) + pce_put_bat_row(0, dy, &chase_title_bat[(word)src * CHASE_TITLE_W], 32); + else + pce_put_bat_row(0, dy, blank_row, 32); + } +} + +/* Only rewrite rows that change. Blank→blank is skipped (BYR wrap isn't + * viable here: title is taller than the empty gap on a 32-row BAT). */ +void draw_title_bat_delta(int old_off, int new_off) { + byte dy; + static word blank_row[32]; + static byte blank_init; + if (!blank_init) { + byte x; + for (x = 0; x < 32; x++) + blank_row[x] = PCE_BAT(TILE0 + TILE_EMPTY, 0); + blank_init = 1; + } + if (old_off == new_off) return; + for (dy = 0; dy < 28; dy++) { + int src_o = (int)dy - old_off; + int src_n = (int)dy - new_off; + byte on_o = (byte)(src_o >= 0 && src_o < (int)CHASE_TITLE_H); + byte on_n = (byte)(src_n >= 0 && src_n < (int)CHASE_TITLE_H); + if (!on_o && !on_n) continue; + if (on_o && on_n && src_o == src_n) continue; + if (on_n) + pce_put_bat_row(0, dy, &chase_title_bat[(word)src_n * CHASE_TITLE_W], 32); + else + pce_put_bat_row(0, dy, blank_row, 32); + } +} + +void draw_title_bat(void) { + draw_title_bat_at(0); +} + +void draw_level_bat(void) { + byte y; + for (y = 0; y < CHASE_LEVEL_H; y++) + pce_put_bat_row(0, y, &chase_level_bat[(word)y * CHASE_LEVEL_W], 32); +} + +/* NES largeNums: digit 1..5 as 2×3 tiles at nametable (20,12). */ +void put_large_digit(byte digit) { + byte j, r; + if (digit < 1) digit = 1; + if (digit > 5) digit = 5; + j = (byte)((digit - 1) << 1); + for (r = 0; r < 3; r++) { + pce_put_tile(20, (byte)(12 + r), PCE_BAT(TILE0 + chase_large_nums[j], PAL_HUD)); + pce_put_tile(21, (byte)(12 + r), PCE_BAT(TILE0 + chase_large_nums[j + 1], PAL_HUD)); + j = (byte)(j + 10); + } +} + +/* NES blink colors: 0x0f black, 0x20 gray/white */ +#define COL_BLINK_OFF PCE_RGB(0, 0, 0) +#define COL_BLINK_ON PCE_RGB(5, 5, 5) +/* NES scroll(-8,…): content nudged right (BXR decreases). */ +#define TITLE_BXR ((word)(0x400 - 8)) +/* NES scroll(-4,…) on level banner */ +#define LEVEL_BXR ((word)(0x400 - 4)) + void title_screen(void) { + byte wait; + int iy, dy; + byte i; + int last_tiles; + hide_all_sprites(); - pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); - put_string(13, 10, "CHASE"); - put_string(9, 14, "PRESS RUN / I"); - wait_for_fire(); + pce_disp_off(); + pce_band_disable(); + pce_load_nes_pal(0, chase_title_pal); + pce_load_nes_pal(256, chase_spr_pal); + pce_scroll(TITLE_BXR, 0); + pce_satb_clear(); + pce_satb_update(); + + /* + * Soft tile offset (no BYR wrap): title starts fully above the screen + * and drops in from the top. iy is in pixels (NES FP units). + */ + iy = -(224 << FP_BITS); + dy = 8 << FP_BITS; + last_tiles = -100; + draw_title_bat_at(iy >> (FP_BITS + 3)); + last_tiles = iy >> (FP_BITS + 3); + pce_disp_on(); + + wait_frames(20); + wait = 160; + frame_cnt = 0; + read_controls(); + fire_prev = 1; + + while (1) { + int tiles; + wait_frame(); + tiles = iy >> (FP_BITS + 3); + if (tiles != last_tiles) { + draw_title_bat_delta(last_tiles, tiles); + last_tiles = tiles; + } + + read_controls(); + if (joy_fire && !fire_prev) break; + fire_prev = joy_fire; + + iy += dy; + if (iy > 0) { + iy = 0; + dy = -dy >> 1; + } + if (dy < (8 << FP_BITS)) dy += 2; + + if (wait) + --wait; + else { + pce_set_color(2, (frame_cnt & 32) ? COL_BLINK_OFF : COL_BLINK_ON); + ++frame_cnt; + } + } + + if (last_tiles != 0) + draw_title_bat_delta(last_tiles, 0); + for (i = 0; i < 16; i++) { + pce_set_color(2, (i & 1) ? COL_BLINK_OFF : COL_BLINK_ON); + wait_frames(4); + } + pce_scroll(0, 0); } void show_level_banner(void) { hide_all_sprites(); - pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); - put_string(11, 12, "LEVEL"); - put_digit(17, 12, (byte)(game_level + 1)); + pce_disp_off(); + load_level_palette(game_level); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, PAL_HUD)); + draw_level_bat(); + put_large_digit((byte)(game_level + 1)); + pce_scroll(LEVEL_BXR, 0); + pce_disp_on(); wait_frames(50); + pce_scroll(0, 0); } void show_game_over(void) { + byte blink = 0; hide_all_sprites(); - pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + pce_disp_off(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, PAL_HUD)); put_string(11, 12, "GAME OVER"); - wait_for_fire(); + pce_disp_on(); + read_controls(); + fire_prev = 1; + while (1) { + wait_frame(); + read_controls(); + blink++; + if ((blink & 1) == 0) + pce_set_color(2, (blink & 2) ? PCE_RGB(5, 1, 4) : PCE_RGB(2, 4, 7)); + if (joy_fire && !fire_prev) break; + fire_prev = joy_fire; + } + while (joy_fire) { wait_frame(); read_controls(); } } void show_well_done(void) { + byte blink = 0; hide_all_sprites(); - pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, 0)); + pce_disp_off(); + pce_fill_bat(0, 0, 32, 28, PCE_BAT(TILE0 + TILE_EMPTY, PAL_HUD)); put_string(11, 12, "WELL DONE"); - wait_for_fire(); + pce_disp_on(); + read_controls(); + fire_prev = 1; + while (1) { + wait_frame(); + read_controls(); + blink++; + if ((blink & 1) == 0) + pce_set_color(2, (blink & 2) ? PCE_RGB(0, 3, 6) : PCE_RGB(2, 4, 7)); + if (joy_fire && !fire_prev) break; + fire_prev = joy_fire; + } + while (joy_fire) { wait_frame(); read_controls(); } } void game_loop(void) { diff --git a/presets/pce/chase_gfx.h b/presets/pce/chase_gfx.h index 5244f0ac1..69a528466 100644 --- a/presets/pce/chase_gfx.h +++ b/presets/pce/chase_gfx.h @@ -1,9 +1,16 @@ -/* Auto-generated by scripts/gen_pce_chase_gfx.py — do not edit */ +/* Generated by scripts/gen_pce_chase_gfx.py. + * Tile/sprite/palette arrays are tagged for the 8bitworkshop Asset Editor. + * Re-run the script to refresh from presets/nes/chase/tileset.chr. + */ #ifndef CHASE_GFX_H #define CHASE_GFX_H -#define CHASE_NTILE 58 -#define CHASE_NSPR 3 +#define CHASE_NTILE 92 +#define CHASE_NSPR 4 +#define CHASE_TITLE_W 32 +#define CHASE_TITLE_H 28 +#define CHASE_LEVEL_W 32 +#define CHASE_LEVEL_H 28 #define TILE_EMPTY 0 #define TILE_FLOOR 1 @@ -23,158 +30,497 @@ #define TILE_COLON 26 #define TILE_SLASH 27 #define TILE_LETTER 32 +#define TILE_BANNER0 58 +#define TILE_BANNER_N 34 + +#define PAL_HUD 0 +#define PAL_WALL 1 +/* Floor + gems share NES attr pal 2: black, floor bg, 2 gem colours */ +#define PAL_FLOOR 2 +#define PAL_GEM PAL_FLOOR +#define PAL_WALLB 3 #define SPR_PLAYER 0 #define SPR_PLAYER2 1 #define SPR_ENEMY 2 +#define SPR_ENEMY2 3 -const unsigned char chase_tiles[1856] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x00, 0xFF, 0x7F, 0xFF, 0x7F, 0xE0, 0x7F, 0xEF, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0x00, 0xFC, 0xFE, 0xFA, 0xFC, 0x06, 0xF8, 0xF6, 0xF8, 0x16, 0xE8, 0x16, 0xE8, 0x16, 0xE8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE8, 0x7F, 0xE8, 0x7F, 0xE8, 0x7F, 0xEF, 0x78, 0xE0, 0x7F, 0xDF, 0x60, 0xBF, 0x40, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x16, 0xE8, 0x16, 0xE8, 0x16, 0xE8, 0xF6, 0x08, 0x06, 0xF8, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0xAC, 0x00, 0x58, 0x03, 0xA3, 0x07, 0x53, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0x2E, 0x00, 0x1E, 0xC0, 0x8E, 0xE0, 0x40, 0xA0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE2, 0x07, 0xE1, 0x06, 0xE0, 0x03, 0x00, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8A, 0x20, 0x05, 0x20, 0x0A, 0xC0, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x04, 0x00, 0xA8, 0x03, 0x53, 0x07, 0xA3, 0x07, 0x52, 0x07, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEA, 0x00, 0xE5, 0x00, 0xEA, 0x00, 0x05, 0x00, 0x0E, 0xC0, 0x8E, 0xE0, 0x4E, 0xA0, 0x80, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xE1, 0x06, 0xE0, 0x03, 0xE8, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0A, 0x20, 0x05, 0xC0, 0x2A, 0x00, 0x05, 0x00, 0xAE, 0x00, 0x5E, 0x00, 0xAE, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x38, 0x38, 0x78, 0x78, 0x78, 0x78, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x7C, 0x7C, 0x7C, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x7C, 0x7E, 0x7E, 0x0E, 0x0E, 0x7E, 0x7E, 0xFC, 0xFC, 0xE0, 0xE0, 0xFE, 0xFE, 0xFE, 0xFE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFC, 0xFC, 0xFE, 0xFE, 0x0E, 0x0E, 0x3C, 0x3C, 0x3E, 0x3E, 0x0E, 0x0E, 0xFE, 0xFE, 0xFC, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3E, 0x3E, 0x7E, 0x7E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xFE, 0xFE, 0xFE, 0xFE, 0x0E, 0x0E, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFC, 0xFC, 0xFC, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xFE, 0xFE, 0x0E, 0x0E, 0xFE, 0xFE, 0xFC, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x7C, 0xFC, 0xFC, 0xE0, 0xE0, 0xFC, 0xFC, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0xFE, 0xFE, 0xFE, 0x0E, 0x0E, 0x1C, 0x1C, 0x1C, 0x1C, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7C, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7C, 0x7C, 0xFE, 0xFE, 0xEE, 0xEE, 0xFE, 0xFE, 0x7E, 0x7E, 0x0E, 0x0E, 0x3E, 0x3E, 0x3C, 0x3C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0xFE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7E, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xC6, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xCE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFC, 0x00, 0xE0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7C, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0xFE, 0x00, 0x76, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x0E, 0x00, 0xFE, 0x00, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xC6, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xFE, 0x00, 0xFE, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xFE, 0x00, 0xFE, +/* BAT entry from title/level pack: low 12 = tile code, high 4 = BG pal */ +#define CHASE_TITLE_CODE(w) ((unsigned short)((w) & 0x0FFF)) +#define CHASE_TITLE_PAL(w) ((unsigned short)((w) >> 12)) + +/* BG tiles: SMS planar in ROM; pce_load_tiles_planar() → VDC format */ +const unsigned char chase_tiles[2944] = /*{w:8,h:8,bpp:1,count:92,brev:1,np:4,pofs:1,sl:4}*/ { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x00, + 0xEF, 0x7F, 0x00, 0x00, 0xE8, 0x7F, 0x00, 0x00, 0xE8, 0x7F, 0x00, 0x00, 0xE8, 0x7F, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0x00, 0x00, 0xFA, 0xFC, 0x00, 0x00, 0x06, 0xF8, 0x00, 0x00, + 0xF6, 0xF8, 0x00, 0x00, 0x16, 0xE8, 0x00, 0x00, 0x16, 0xE8, 0x00, 0x00, 0x16, 0xE8, 0x00, 0x00, + 0xE8, 0x7F, 0x00, 0x00, 0xE8, 0x7F, 0x00, 0x00, 0xE8, 0x7F, 0x00, 0x00, 0xEF, 0x78, 0x00, 0x00, + 0xE0, 0x7F, 0x00, 0x00, 0xDF, 0x60, 0x00, 0x00, 0xBF, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x16, 0xE8, 0x00, 0x00, 0x16, 0xE8, 0x00, 0x00, 0x16, 0xE8, 0x00, 0x00, 0xF6, 0x08, 0x00, 0x00, + 0x06, 0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xAC, 0x00, 0x00, 0x00, 0x58, 0x03, 0x00, 0x00, 0xA3, 0x07, 0x00, 0x00, 0x53, 0x07, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x2E, 0x00, 0x00, 0x00, 0x1E, 0xC0, 0x00, 0x00, 0x8E, 0xE0, 0x00, 0x00, 0x40, 0xA0, 0x00, 0x00, + 0xE2, 0x07, 0x00, 0x00, 0xE1, 0x06, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x8A, 0x20, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x0A, 0xC0, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xA8, 0x03, 0x00, 0x00, 0x53, 0x07, 0x00, 0x00, 0xA3, 0x07, 0x00, 0x00, 0x52, 0x07, 0x00, 0x00, + 0xEA, 0x00, 0x00, 0x00, 0xE5, 0x00, 0x00, 0x00, 0xEA, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x0E, 0xC0, 0x00, 0x00, 0x8E, 0xE0, 0x00, 0x00, 0x4E, 0xA0, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, + 0xE1, 0x06, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x0A, 0x20, 0x00, 0x00, 0x05, 0xC0, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xAE, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0xAE, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7C, 0x7C, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, + 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, + 0x38, 0x38, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0x78, 0x78, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, + 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, + 0x7C, 0x7C, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, + 0x3E, 0x3E, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x3E, 0x3E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, + 0xEE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x7C, 0x7C, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, + 0x1C, 0x1C, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, 0x38, 0x38, 0x00, 0x00, + 0x7C, 0x7C, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7C, 0x7C, 0x00, 0x00, + 0x7C, 0x7C, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xEE, 0xEE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x3E, 0x3E, 0x00, 0x00, 0x3C, 0x3C, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, + 0x00, 0x0E, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xC6, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xCE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, + 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, + 0x00, 0x78, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, + 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xFC, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, + 0x00, 0xF0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, + 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, + 0x1F, 0x1F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, + 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, + 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, + 0x0F, 0x0F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0xE0, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0x0F, 0x0F, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, + 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, + 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x07, 0x07, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, + 0xF0, 0xF0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, + 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, + 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x7F, 0x7F, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, + 0x7F, 0x7F, 0x00, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, + 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, 0x7E, 0x7E, 0x00, 0x00, + 0xFC, 0xFC, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, 0xF8, 0xF8, 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -const unsigned char chase_sprites[384] = { - 0x00, 0x00, 0xFC, 0x3F, 0x06, 0x60, 0xF2, 0x5F, 0xF2, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, - 0xFA, 0x5F, 0xF2, 0x5F, 0xF2, 0x5F, 0xE2, 0x47, 0xE6, 0x67, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0xFC, 0x3F, 0x8C, 0x31, 0xB4, 0x2D, 0x94, 0x29, 0x94, 0x29, - 0x84, 0x21, 0xFC, 0x3F, 0xFC, 0x3F, 0x1C, 0x38, 0xD8, 0x1B, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFC, 0x3F, 0x06, 0x60, 0xF2, 0x5F, 0xF2, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, 0xFA, 0x5F, - 0xF2, 0x5F, 0xF2, 0x5F, 0xE2, 0x47, 0xE6, 0x67, 0xFE, 0x7F, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF8, 0x1F, 0xFC, 0x3F, 0x8C, 0x31, 0xB4, 0x2D, 0x94, 0x29, 0x94, 0x29, 0x84, 0x21, - 0xFC, 0x3F, 0xFC, 0x3F, 0x1C, 0x38, 0xD8, 0x1B, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x7F, 0x02, 0x40, 0xF2, 0x5F, 0xFE, 0x7F, 0xFA, 0x5F, 0x7A, 0x5E, 0xFA, 0x5F, - 0xFA, 0x5F, 0xF2, 0x5F, 0xF2, 0x5F, 0xD2, 0x4B, 0xE6, 0x67, 0xFC, 0x3F, 0xF8, 0x1F, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0xFC, 0x3F, 0x00, 0x00, 0x04, 0x20, 0x94, 0x29, 0x94, 0x29, - 0xB4, 0x2D, 0x8C, 0x31, 0xFC, 0x3F, 0x3C, 0x3C, 0x98, 0x19, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +/* Sprites: 16-bit words, bit15=left (LE bytes match VDC sprite CHR) */ +const unsigned short chase_sprites[256] = /*{w:16,h:16,bpp:1,count:4,brev:1,np:4,pofs:16,sl:1,bpw:16,wpimg:64}*/ { + 0x0000, 0x3FFC, 0x6006, 0x5FF2, 0x5FF2, 0x5FFA, 0x5FFA, 0x5FFA, + 0x5FFA, 0x5FF2, 0x5FF2, 0x47E2, 0x67E6, 0x7FFE, 0x3FFC, 0x0000, + 0x0000, 0x0000, 0x1FF8, 0x3FFC, 0x318C, 0x2DB4, 0x2994, 0x2994, + 0x2184, 0x3FFC, 0x3FFC, 0x381C, 0x1BD8, 0x0180, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x3FFC, 0x6006, 0x5FF2, 0x5FF2, 0x5FFA, 0x5FFA, 0x5FFA, 0x5FFA, + 0x5FF2, 0x5FF2, 0x47E2, 0x67E6, 0x7FFE, 0x3FFC, 0x0000, 0x0000, + 0x0000, 0x1FF8, 0x3FFC, 0x318C, 0x2DB4, 0x2994, 0x2994, 0x2184, + 0x3FFC, 0x3FFC, 0x381C, 0x1BD8, 0x0180, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x7FFE, 0x4002, 0x5FF2, 0x7FFE, 0x5FFA, 0x5E7A, 0x5FFA, + 0x5FFA, 0x5FF2, 0x5FF2, 0x4BD2, 0x67E6, 0x3FFC, 0x1FF8, 0x0000, + 0x0000, 0x0000, 0x3FFC, 0x3FFC, 0x0000, 0x2004, 0x2994, 0x2994, + 0x2DB4, 0x318C, 0x3FFC, 0x3C3C, 0x1998, 0x03C0, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x7FFE, 0x4002, 0x5FF2, 0x7FFE, 0x5FFA, 0x5E7A, 0x5FFA, 0x5FFA, + 0x5FF2, 0x5FF2, 0x4BD2, 0x67E6, 0x3FFC, 0x1FF8, 0x0000, 0x0000, + 0x0000, 0x3FFC, 0x3FFC, 0x0000, 0x2004, 0x2994, 0x2994, 0x2DB4, + 0x318C, 0x3FFC, 0x3C3C, 0x1998, 0x03C0, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, +}; + +const unsigned short chase_bg_pal_l1[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x0C6, 0x167, 0x1FF, 0x000, 0x104, 0x186, 0x1E7, 0x000, 0x0C0, 0x138, 0x1FC, 0x000, 0x0C6, 0x117, 0x167 }; +const unsigned short chase_bg_pal_l2[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x0C6, 0x167, 0x1FF, 0x000, 0x0C6, 0x117, 0x167, 0x000, 0x0A0, 0x138, 0x1FC, 0x000, 0x08E, 0x0DF, 0x16F }; +const unsigned short chase_bg_pal_l3[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x0C6, 0x167, 0x1FF, 0x000, 0x06C, 0x0F5, 0x17E, 0x000, 0x022, 0x138, 0x1FC, 0x000, 0x08E, 0x0DF, 0x16F }; +#define chase_bg_pal chase_bg_pal_l1 +const unsigned short chase_title_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x000, 0x000, 0x000, 0x000, 0x104, 0x186, 0x1E7, 0x000, 0x086, 0x117, 0x167, 0x000, 0x05E, 0x0AE, 0x137 }; +const unsigned short chase_spr_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x000, 0x1E0, 0x1FF, 0x000, 0x000, 0x0FA, 0x1FF, 0x000, 0x000, 0x0AE, 0x1FF, 0x000, 0x000, 0x117, 0x1FF }; + +/* Per-level BG palette pointers (L4/L5 share L3, matching NES). */ +const unsigned short* const chase_level_pal[5] = { + chase_bg_pal_l1, chase_bg_pal_l2, chase_bg_pal_l3, + chase_bg_pal_l3, chase_bg_pal_l3 }; -const unsigned short chase_bg_pal[16] = { 0x000, 0x04E, 0x1B6, 0x1FF, 0x000, 0x0B6, 0x16E, 0x1B6, 0x000, 0x048, 0x0E8, 0x1F0, 0x000, 0x04E, 0x096, 0x1DE }; -const unsigned short chase_spr_pal[16] = { 0x000, 0x000, 0x1C8, 0x1FF, 0x000, 0x000, 0x1C4, 0x1FF, 0x000, 0x000, 0x1A4, 0x1FF, 0x000, 0x000, 0x096, 0x1FF }; +const unsigned short chase_title_bat[896] = { + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x2102, 0x2103, + 0x0100, 0x0100, 0x2102, 0x2103, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x2102, 0x2103, 0x2102, 0x2103, 0x2102, 0x2103, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1102, 0x1103, 0x1102, 0x1103, 0x1102, 0x1103, 0x2104, 0x2105, + 0x0100, 0x0100, 0x2104, 0x2105, 0x3102, 0x3103, 0x3102, 0x3103, + 0x3102, 0x3103, 0x2104, 0x2105, 0x2104, 0x2105, 0x2104, 0x2105, + 0x1102, 0x1103, 0x1102, 0x1103, 0x1102, 0x1103, 0x0100, 0x0100, + 0x1104, 0x1105, 0x1104, 0x1105, 0x1104, 0x1105, 0x2102, 0x2103, + 0x0100, 0x0100, 0x2102, 0x2103, 0x3104, 0x3105, 0x3104, 0x3105, + 0x3104, 0x3105, 0x2102, 0x2103, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1104, 0x1105, 0x1104, 0x1105, 0x1104, 0x1105, 0x0100, 0x0100, + 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, 0x2104, 0x2105, + 0x0100, 0x0100, 0x2104, 0x2105, 0x3102, 0x3103, 0x0100, 0x0100, + 0x3102, 0x3103, 0x2104, 0x2105, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, 0x2102, 0x2103, + 0x2102, 0x2103, 0x2102, 0x2103, 0x3104, 0x3105, 0x0100, 0x0100, + 0x3104, 0x3105, 0x2102, 0x2103, 0x2102, 0x2103, 0x2102, 0x2103, + 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, 0x2104, 0x2105, + 0x2104, 0x2105, 0x2104, 0x2105, 0x3102, 0x3103, 0x0100, 0x0100, + 0x3102, 0x3103, 0x2104, 0x2105, 0x2104, 0x2105, 0x2104, 0x2105, + 0x1102, 0x1103, 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, 0x2102, 0x2103, + 0x0100, 0x0100, 0x2102, 0x2103, 0x3104, 0x3105, 0x0100, 0x0100, + 0x3104, 0x3105, 0x0100, 0x0100, 0x0100, 0x0100, 0x2102, 0x2103, + 0x1104, 0x1105, 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, 0x2104, 0x2105, + 0x0100, 0x0100, 0x2104, 0x2105, 0x3102, 0x3103, 0x3102, 0x3103, + 0x3102, 0x3103, 0x0100, 0x0100, 0x0100, 0x0100, 0x2104, 0x2105, + 0x1102, 0x1103, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, 0x2102, 0x2103, + 0x0100, 0x0100, 0x2102, 0x2103, 0x3104, 0x3105, 0x3104, 0x3105, + 0x3104, 0x3105, 0x2102, 0x2103, 0x2102, 0x2103, 0x2102, 0x2103, + 0x1104, 0x1105, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1102, 0x1103, 0x1102, 0x1103, 0x1102, 0x1103, 0x2104, 0x2105, + 0x0100, 0x0100, 0x2104, 0x2105, 0x3102, 0x3103, 0x0100, 0x0100, + 0x3102, 0x3103, 0x2104, 0x2105, 0x2104, 0x2105, 0x2104, 0x2105, + 0x1102, 0x1103, 0x1102, 0x1103, 0x1102, 0x1103, 0x0100, 0x0100, + 0x1104, 0x1105, 0x1104, 0x1105, 0x1104, 0x1105, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x3104, 0x3105, 0x0100, 0x0100, + 0x3104, 0x3105, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x1104, 0x1105, 0x1104, 0x1105, 0x1104, 0x1105, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x012F, 0x0131, 0x0124, 0x0132, 0x0132, 0x0100, 0x0100, + 0x0132, 0x0133, 0x0120, 0x0131, 0x0133, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x212F, 0x2123, 0x2112, 0x2110, 0x2111, 0x2112, 0x0100, + 0x2132, 0x2127, 0x2128, 0x2131, 0x2134, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, +}; + +const unsigned short chase_level_bat[896] = { + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x013D, 0x0100, 0x013B, 0x013C, 0x013D, 0x013E, 0x013B, + 0x013C, 0x013D, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x013D, 0x0100, 0x013B, 0x013F, 0x013D, 0x013E, 0x013B, + 0x013F, 0x013D, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0140, 0x0144, 0x0140, 0x0141, 0x0142, 0x0143, 0x0140, + 0x0141, 0x0140, 0x0144, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, + 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, 0x0100, +}; + +/* NES largeNums[] mapped to PCE tile indices — 3 rows × 5 digits (2 tiles each) */ +const unsigned char chase_large_nums[30] = { + 69, 70, 71, 72, 71, 72, 73, 74, 75, 76, + 77, 70, 78, 79, 80, 81, 82, 83, 84, 72, + 85, 86, 87, 88, 89, 90, 91, 74, 89, 90, +}; #endif diff --git a/presets/pce/gfxtest.c b/presets/pce/gfxtest.c index 5530d7e0b..c017a0969 100644 --- a/presets/pce/gfxtest.c +++ b/presets/pce/gfxtest.c @@ -56,7 +56,7 @@ static void setup_gfx(void) { pce_load_palette(0, gfxtest_bg_pal, 16); pce_load_palette(256, gfxtest_spr_pal, 16); - pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_load_tiles_planar(TILE0, gfxtest_tiles, GFXTEST_NTILE); pce_load_sprites(SPR0, gfxtest_sprites, GFXTEST_NSPR); draw_playfield(); diff --git a/presets/pce/gfxtest_gfx.h b/presets/pce/gfxtest_gfx.h index 928c2de3e..74b8a0c0c 100644 --- a/presets/pce/gfxtest_gfx.h +++ b/presets/pce/gfxtest_gfx.h @@ -5,47 +5,48 @@ #define GFXTEST_NTILE 5 #define GFXTEST_NSPR 3 -const unsigned char gfxtest_tiles[160] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA, 0x55, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0xFF, 0x88, 0xFF, 0x88, 0xFF, 0x88, 0xFF, 0xFF, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, 0xA0, 0xFF, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xEF, 0x00, 0xEF, 0x00, 0xC7, 0x00, 0x83, 0x00, 0xC7, 0x00, 0xEF, 0x00, 0xEF, 0x00, 0xFF, 0x00, - 0x10, 0x00, 0x10, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, +/* BG tiles: SMS planar in ROM; pce_load_tiles_planar() → VDC format */ +const unsigned char gfxtest_tiles[160] = /*{w:8,h:8,bpp:1,count:5,brev:1,np:4,pofs:1,sl:4}*/ { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + 0x55, 0xAA, 0x00, 0x00, 0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA, 0x00, 0x00, 0xAA, 0x55, 0x00, 0x00, + 0x55, 0xAA, 0x00, 0x00, 0xAA, 0x55, 0x00, 0x00, 0x55, 0xAA, 0x00, 0x00, 0xAA, 0x55, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0x88, 0xFF, 0x00, 0x00, 0x88, 0xFF, 0x00, 0x00, 0x88, 0xFF, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xA0, 0xFF, 0x00, 0x00, 0xA0, 0xFF, 0x00, 0x00, 0xA0, 0xFF, 0x00, 0x00, + 0xEF, 0x00, 0x10, 0x00, 0xEF, 0x00, 0x10, 0x00, 0xC7, 0x00, 0x38, 0x00, 0x83, 0x00, 0x7C, 0x00, + 0xC7, 0x00, 0x38, 0x00, 0xEF, 0x00, 0x10, 0x00, 0xEF, 0x00, 0x10, 0x00, 0xFF, 0x00, 0x00, 0x00, }; -const unsigned char gfxtest_sprites[384] = { - 0x80, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xE0, 0x07, 0x60, 0x06, 0xF0, 0x0F, 0xF0, 0x0F, 0x78, 0x1E, - 0x78, 0x1E, 0xFC, 0x3F, 0xDC, 0x3B, 0x8E, 0x71, 0x86, 0x61, 0x80, 0x01, 0x40, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, - 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x40, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0x03, 0xF0, 0x0F, 0xF8, 0x1F, 0x1C, 0x38, 0x0C, 0x30, 0x0E, 0x70, 0x0E, 0x70, - 0x0E, 0x70, 0x0E, 0x70, 0x0C, 0x30, 0x1C, 0x38, 0xF8, 0x1F, 0xF0, 0x0F, 0xC0, 0x03, 0x00, 0x00, - 0x00, 0x00, 0xC0, 0x03, 0x30, 0x0C, 0x08, 0x10, 0xE4, 0x27, 0xF4, 0x29, 0xF2, 0x4B, 0xF2, 0x4F, - 0xF2, 0x4F, 0xF2, 0x4F, 0xF4, 0x2F, 0xE4, 0x27, 0x08, 0x10, 0x30, 0x0C, 0xC0, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x10, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x30, 0x0C, 0x60, 0x06, 0xF0, 0x0F, 0xF8, 0x1F, 0xEC, 0x37, 0xEC, 0x37, 0xFC, 0x3F, - 0xFC, 0x3F, 0x30, 0x0C, 0x18, 0x18, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +const unsigned short gfxtest_sprites[192] = /*{w:16,h:16,bpp:1,count:3,brev:1,np:4,pofs:16,sl:1,bpw:16,wpimg:64}*/ { + 0x0180, 0x03C0, 0x03C0, 0x07E0, 0x0660, 0x0FF0, 0x0FF0, 0x1E78, + 0x1E78, 0x3FFC, 0x3BDC, 0x718E, 0x6186, 0x0180, 0x0240, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0180, + 0x0180, 0x0000, 0x0000, 0x0000, 0x0180, 0x0180, 0x0240, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03C0, 0x0FF0, 0x1FF8, 0x381C, 0x300C, 0x700E, 0x700E, + 0x700E, 0x700E, 0x300C, 0x381C, 0x1FF8, 0x0FF0, 0x03C0, 0x0000, + 0x0000, 0x03C0, 0x0C30, 0x1008, 0x27E4, 0x29F4, 0x4BF2, 0x4FF2, + 0x4FF2, 0x4FF2, 0x2FF4, 0x27E4, 0x1008, 0x0C30, 0x03C0, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0600, 0x0400, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0810, 0x0810, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0C30, 0x0660, 0x0FF0, 0x1FF8, 0x37EC, 0x37EC, 0x3FFC, + 0x3FFC, 0x0C30, 0x1818, 0x300C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; -const unsigned short gfxtest_bg_pal[16] = { 0x000, 0x049, 0x12E, 0x0B4, 0x1FF, 0x038, 0x1C0, 0x0FF, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; -const unsigned short gfxtest_spr_pal[16] = { 0x000, 0x1FF, 0x038, 0x0E8, 0x1FF, 0x1C0, 0x049, 0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short gfxtest_bg_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x049, 0x12E, 0x0B4, 0x1FF, 0x038, 0x1C0, 0x0FF, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short gfxtest_spr_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x1FF, 0x038, 0x0E8, 0x1FF, 0x1C0, 0x049, 0x092, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; #endif diff --git a/presets/pce/pcegfx.c b/presets/pce/pcegfx.c index 57932376d..d6e97ba0b 100644 --- a/presets/pce/pcegfx.c +++ b/presets/pce/pcegfx.c @@ -79,8 +79,9 @@ void pce_disp_on(void) { } void pce_scroll(word x, word y) { - vdc_reg(VDC_BXR, x); + /* BYR is latched before BXR each scanline — write Y first. */ vdc_reg(VDC_BYR, y); + vdc_reg(VDC_BXR, x); } /* Asm: pcegfx_tia.s */ @@ -189,45 +190,110 @@ void pce_load_palette(word index, const word *colors, word count) { } } +void pce_load_nes_pal(word base, const word *colors) { + byte p, c; + for (p = 0; p < 4; p++) { + word idx = (word)(base + ((word)p << 4)); + VCE_ADDR_LO = (unsigned char)idx; + VCE_ADDR_HI = (unsigned char)(idx >> 8); + for (c = 0; c < 4; c++) { + word col = colors[(word)p * 4 + c]; + VCE_DATA_LO = (unsigned char)col; + VCE_DATA_HI = (unsigned char)(col >> 8); + } + } +} + +/* Word-by-word VRAM poke (no TIA). Large ROM→VRAM TIA transfers were only + * committing the first tile pattern(s) in Chase; poke is slower but reliable. */ +static void vram_poke_words(word vaddr, const word *data, byte n) { + const unsigned char *p = (const unsigned char *)data; + VDC_CTRL = VDC_MAWR; + VDC_DATA_LO = (unsigned char)vaddr; + VDC_DATA_HI = (unsigned char)(vaddr >> 8); + VDC_CTRL = VDC_VWR; + while (n--) { + VDC_DATA_LO = *p++; + VDC_DATA_HI = *p++; + } +} + void pce_load_tiles(word tile_index, const void *data, word ntiles) { - pce_load_vram((word)(tile_index << 4), data, (word)(ntiles << 4)); + const unsigned char *p = (const unsigned char *)data; + while (ntiles--) { + byte i; + word addr = (word)(tile_index << 4); + VDC_CTRL = VDC_MAWR; + VDC_DATA_LO = (unsigned char)addr; + VDC_DATA_HI = (unsigned char)(addr >> 8); + VDC_CTRL = VDC_VWR; + for (i = 0; i < 32; i += 2) { + VDC_DATA_LO = p[i]; + VDC_DATA_HI = p[i + 1]; + } + p += 32; + tile_index++; + } } -void pce_load_sprites(word pattern, const void *data, word npatterns) { - pce_load_vram((word)(pattern << 5), data, (word)(npatterns << 6)); +/* SMS/4-plane row format → VDC bitplane-pair format (one tile at a time). */ +void pce_load_tiles_planar(word tile_index, const void *data, word ntiles) { + const unsigned char *p = (const unsigned char *)data; + unsigned char buf[32]; + while (ntiles--) { + byte y; + for (y = 0; y < 8; y++) { + buf[y * 2] = p[y * 4]; + buf[y * 2 + 1] = p[y * 4 + 1]; + buf[16 + y * 2] = p[y * 4 + 2]; + buf[16 + y * 2 + 1] = p[y * 4 + 3]; + } + pce_load_tiles(tile_index, buf, 1); + p += 32; + tile_index++; + } } -void pce_put_tile(byte x, byte y, word bat) { - word w = bat; - pce_vram_burst(PCE_BAT_ADDR_XY(x, y), &w, 2); +void pce_load_sprites(word pattern, const void *data, word npatterns) { + const unsigned char *p = (const unsigned char *)data; + while (npatterns--) { + byte i; + word addr = (word)(pattern << 5); + VDC_CTRL = VDC_MAWR; + VDC_DATA_LO = (unsigned char)addr; + VDC_DATA_HI = (unsigned char)(addr >> 8); + VDC_CTRL = VDC_VWR; + for (i = 0; i < 128; i += 2) { + VDC_DATA_LO = p[i]; + VDC_DATA_HI = p[i + 1]; + } + p += 128; + pattern += 2; + } } void pce_put_bat_row(byte x, byte y, const word *bats, byte n) { if (!n) return; - pce_vram_burst(PCE_BAT_ADDR_XY(x, y), bats, (unsigned int)n << 1); + vram_poke_words(PCE_BAT_ADDR_XY(x, y), bats, n); } -void pce_fill_bat(byte x, byte y, byte w, byte h, word bat) { - byte row; - unsigned char lo = (unsigned char)bat; - unsigned char hi = (unsigned char)(bat >> 8); - byte i; +/* pce_put_tile is in pcegfx_tia.s. This 4-byte-arg variant keeps bat off AX. */ +void pce_put_tile_raw(byte x, byte y, byte bat_lo, byte bat_hi) { + word addr = (word)(((word)y << 5) + x); + VDC_CTRL = VDC_MAWR; + VDC_DATA_LO = (unsigned char)addr; + VDC_DATA_HI = (unsigned char)(addr >> 8); + VDC_CTRL = VDC_VWR; + VDC_DATA_LO = bat_lo; + VDC_DATA_HI = bat_hi; +} - for (i = 0; i < 64; i += 2) { - fillbuf[i] = lo; - fillbuf[i + 1] = hi; - } - for (row = 0; row < h; ++row) { - word addr = PCE_BAT_ADDR_XY(x, (byte)(y + row)); - word left = w; - while (left) { - byte chunk = left > 32 ? 32 : (byte)left; - pce_vram_burst(addr, fillbuf, (unsigned int)chunk << 1); - addr += chunk; - left = (word)(left - chunk); - } - } +void pce_fill_bat(byte x, byte y, byte w, byte h, word bat) { + byte row, col; + for (row = 0; row < h; ++row) + for (col = 0; col < w; ++col) + pce_put_tile((byte)(x + col), (byte)(y + row), bat); } void pce_load_bat(byte x, byte y, const word *map, byte w, byte h) { diff --git a/presets/pce/pcegfx.h b/presets/pce/pcegfx.h index 89d8230e3..88dd8a940 100644 --- a/presets/pce/pcegfx.h +++ b/presets/pce/pcegfx.h @@ -88,14 +88,24 @@ void pce_fill_vram(word vaddr, word value, word nwords); /* Palette index 0..255 BG, 256..511 sprites; count = # of colors */ void pce_load_palette(word index, const word *colors, word count); void pce_set_color(word index, word color); +/* + * NES-style 4×4 pack → 4 consecutive PCE palettes. + * colors[0..3] → VCE base+0..3, [4..7] → base+16..19, etc. + * Use base 0 for BG, 256 for sprites. + */ +void pce_load_nes_pal(word base, const word *colors); -/* BG tiles: 32 bytes / 16 words each. tile_index is BAT character code. */ +/* BG tiles: 32 bytes / 16 words each. tile_index is BAT character code. + * pce_load_tiles() expects native VDC planar (bitplane pairs). + * pce_load_tiles_planar() expects SMS-style planar (editable in 8bw). */ void pce_load_tiles(word tile_index, const void *data, word ntiles); +void pce_load_tiles_planar(word tile_index, const void *data, word ntiles); /* Sprite patterns: 128 bytes / 64 words each (16x16). pattern = VRAM>>5. */ void pce_load_sprites(word pattern, const void *data, word npatterns); void pce_put_tile(byte x, byte y, word bat); +void pce_put_tile_raw(byte x, byte y, byte bat_lo, byte bat_hi); /* Burst-write `n` BAT words starting at (x,y) — one MAWR, then stream. */ void pce_put_bat_row(byte x, byte y, const word *bats, byte n); void pce_fill_bat(byte x, byte y, byte w, byte h, word bat); diff --git a/presets/pce/pcegfx_tia.s b/presets/pce/pcegfx_tia.s index a195238f5..5356ed4f2 100644 --- a/presets/pce/pcegfx_tia.s +++ b/presets/pce/pcegfx_tia.s @@ -17,12 +17,16 @@ .export _pce_band_scroll_enable .export _pce_band_scroll_disable .export _pce_band_catchup + .export _pce_put_tile .import popax + .import popa .importzp tmp1, tmp2, ptr1, vdc_flags VDC_CTRL = $0200 VDC_DATA_LO = $0202 VDC_DATA_HI = $0203 +VDC_MAWR = 0 +VDC_VWR = 2 STATUS_VB = $20 STATUS_BUSY = $40 STATUS_SATBEND = $08 @@ -31,16 +35,13 @@ STATUS_RCR = $04 VDC_RCR = 6 VDC_BXR = 7 -; RAM trampoline: TIA + RTS (copied from ROM by crt0 with .DATA) -.segment "DATA" -tia_stub: - .byte $E3 ; TIA - .word $FFFF ; src (patched) - .word $0202 ; VDC data port - .word $FFFF ; length (patched) - .byte $60 ; RTS - +; BSS trampoline: rebuilt every call so we never depend on .DATA init +; surviving (BSS clear / stack smash / bank quirks can wipe DATA). .segment "BSS" +tia_stub: + .res 8 ; TIA src,dest,len + RTS +put_tile_bat: + .res 2 ; bat lo/hi for pce_put_tile _pce_vsync_overruns: .res 2 ; word — byte wrapped mid-bench _pce_busy_wait_iters: @@ -48,19 +49,67 @@ _pce_busy_wait_iters: .segment "CODE" -; Patch and run TIA. nbytes in tmp1/tmp2, src in ptr1. +; Build and run TIA. nbytes in tmp1/tmp2, src in ptr1. .proc tia_run + lda #$E3 ; TIA opcode + sta tia_stub lda ptr1 sta tia_stub+1 lda ptr1+1 sta tia_stub+2 + lda #<$0202 ; VDC data port + sta tia_stub+3 + lda #>$0202 + sta tia_stub+4 lda tmp1 sta tia_stub+5 lda tmp2 sta tia_stub+6 + lda #$60 ; RTS + sta tia_stub+7 jmp tia_stub .endproc +; void __fastcall__ pce_put_tile(unsigned char x, unsigned char y, +; unsigned int bat); +; bat in A/X. Soft stack [y][x] (y at TOS) per cc65 call setup. +; Bat saved in BSS — ZP tmp1/tmp2 are clobbered by IRQ wait helpers. +.proc _pce_put_tile + sta put_tile_bat ; bat lo + stx put_tile_bat+1 ; bat hi + jsr popa ; y + sta ptr1 + stz ptr1+1 + asl ptr1 + rol ptr1+1 + asl ptr1 + rol ptr1+1 + asl ptr1 + rol ptr1+1 + asl ptr1 + rol ptr1+1 + asl ptr1 + rol ptr1+1 ; ptr1 = y << 5 + jsr popa ; x + clc + adc ptr1 + sta ptr1 + bcc :+ + inc ptr1+1 +: stz VDC_CTRL ; MAWR + lda ptr1 + sta VDC_DATA_LO + lda ptr1+1 + sta VDC_DATA_HI + lda #VDC_VWR + sta VDC_CTRL + lda put_tile_bat + sta VDC_DATA_LO + lda put_tile_bat+1 + sta VDC_DATA_HI + rts +.endproc + ; void __fastcall__ pce_tia_vdc(const void *src, unsigned int nbytes); ; nbytes in A/X, src on soft stack. VWR must already be selected. .proc _pce_tia_vdc @@ -144,10 +193,10 @@ wait_edge: stz _pce_busy_wait_iters stz _pce_busy_wait_iters+1 stz tmp1 ; busy-seen flag - ldy #4 ; 4 × 256 polls max + ldx #4 ; 4 × 256 polls max (X — Y used by band writes) loop: lda VDC_CTRL - sta tmp2 ; preserve status (X gets clobbered) + sta tmp2 ; preserve status and #STATUS_RCR beq :+ jsr band_rcr_from_poll @@ -167,7 +216,7 @@ cont: inc _pce_busy_wait_iters bne loop inc _pce_busy_wait_iters+1 - dey + dex bne loop done: rts .endproc diff --git a/presets/pce/perftest.c b/presets/pce/perftest.c index 4ed76837d..f8db53f8f 100644 --- a/presets/pce/perftest.c +++ b/presets/pce/perftest.c @@ -165,7 +165,7 @@ static void paint_chart(void) { word star = PCE_BAT(TILE0 + 4, 0); /* TIA tests may have clobbered tile data at $1000 — reload. */ - pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_load_tiles_planar(TILE0, gfxtest_tiles, GFXTEST_NTILE); pce_satb_clear(); pce_satb_update(); @@ -235,7 +235,7 @@ static void setup(void) { pce_disp_off(); pce_load_palette(0, gfxtest_bg_pal, 16); pce_load_palette(256, gfxtest_spr_pal, 16); - pce_load_tiles(TILE0, gfxtest_tiles, GFXTEST_NTILE); + pce_load_tiles_planar(TILE0, gfxtest_tiles, GFXTEST_NTILE); pce_load_sprites(SPR0, gfxtest_sprites, GFXTEST_NSPR); for (bi = 0; bi < sizeof(burst_buf); bi++) burst_buf[bi] = (unsigned char)bi; diff --git a/presets/pce/solarian.c b/presets/pce/solarian.c index 2dfa7029f..6368ccb46 100644 --- a/presets/pce/solarian.c +++ b/presets/pce/solarian.c @@ -202,7 +202,7 @@ void form_set_frame(byte spark) { spark ? &solarian_tiles[T_FORM_B * 32] : &solarian_tiles[T_FORM_A * 32]; form_spark = spark; - pce_load_tiles(TILE0 + T_FORM_A, src, T_FORM_NTILE); + pce_load_tiles_planar(TILE0 + T_FORM_A, src, T_FORM_NTILE); } void draw_formation_slot(byte fi) { @@ -560,7 +560,7 @@ static void setup_gfx(void) { pce_disp_off(); pce_load_palette(0, solarian_bg_pal, 16); pce_load_palette(256, solarian_spr_pal, 16); - pce_load_tiles(TILE0, solarian_tiles, SOLARIAN_NTILE); + pce_load_tiles_planar(TILE0, solarian_tiles, SOLARIAN_NTILE); pce_load_sprites(SPR0, solarian_sprites, SOLARIAN_NSPR); pce_satb_clear(); pce_satb_update(); diff --git a/presets/pce/solarian_gfx.h b/presets/pce/solarian_gfx.h index 8b98dde58..1004eb08f 100644 --- a/presets/pce/solarian_gfx.h +++ b/presets/pce/solarian_gfx.h @@ -5,7 +5,7 @@ #define SOLARIAN_NTILE 46 #define SOLARIAN_NSPR 12 -/* BG tiles (8x8, PCE 4bpp) */ +/* BG tiles: SMS planar in ROM; pce_load_tiles_planar() → VDC format */ #define T_BLANK 0 #define T_FORM_A 1 /* live formation slots (3 tiles) */ #define T_FORM_B 4 /* flap frame B source */ @@ -24,201 +24,201 @@ #define S_BULLET 10 #define S_FORM 11 -const unsigned char solarian_tiles[1472] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x04, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFE, 0x06, 0xF9, 0x51, 0xF8, 0x04, 0xF8, 0x02, 0x70, 0x89, 0x70, 0x04, 0x20, 0x02, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0x03, 0x04, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x06, 0x06, 0xD9, 0x01, 0xF8, 0x50, 0xF8, 0x06, 0xF8, 0x01, 0x70, 0x88, 0x70, 0x04, 0x20, 0x03, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x38, 0x00, 0x78, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x0E, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0x00, 0x0E, 0x00, 0x3C, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xFC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x0E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7E, 0x00, 0x0E, 0x00, 0x3C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xF8, 0x00, 0xEC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xEC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xC6, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xCE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xE6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xE0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEC, 0x00, 0x7E, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFC, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7C, 0x00, 0xE0, 0x00, 0x7C, 0x00, 0x0E, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x6C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xEE, 0x00, 0xC6, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x7C, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0xEE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xFE, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xFE, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +const unsigned char solarian_tiles[1472] = /*{w:8,h:8,bpp:1,count:46,brev:1,np:4,pofs:1,sl:4}*/ { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0xFE, 0x06, 0x00, 0x00, 0xF9, 0x51, 0x00, 0x00, 0xF8, 0x04, 0x00, 0x00, 0xF8, 0x02, 0x00, 0x00, + 0x70, 0x89, 0x00, 0x00, 0x70, 0x04, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x03, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x06, 0x06, 0x00, 0x00, 0xD9, 0x01, 0x00, 0x00, 0xF8, 0x50, 0x00, 0x00, 0xF8, 0x06, 0x00, 0x00, + 0xF8, 0x01, 0x00, 0x00, 0x70, 0x88, 0x00, 0x00, 0x70, 0x04, 0x00, 0x00, 0x20, 0x03, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0xEC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xCE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEC, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x6C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, + 0xFE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, + 0x70, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -const unsigned char solarian_sprites[1536] = { - 0x40, 0x01, 0x40, 0x01, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x44, 0x11, 0x44, 0x11, - 0x44, 0x11, 0x34, 0x16, 0x3C, 0x1E, 0x54, 0x15, 0x04, 0x10, 0x04, 0x10, 0x04, 0x10, 0x04, 0x10, - 0xC0, 0x01, 0xC0, 0x01, 0x20, 0x02, 0xF0, 0x07, 0xC0, 0x01, 0xC2, 0x21, 0xC2, 0x21, 0xEA, 0x2B, - 0xFE, 0x3F, 0xFE, 0x3F, 0xFE, 0x3F, 0xDE, 0x3D, 0xEE, 0x3B, 0x1E, 0x3C, 0x0A, 0x28, 0x0A, 0x28, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x10, 0x04, 0x60, 0x03, 0xE0, 0x03, 0xE0, 0x0F, - 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x10, 0x04, 0x08, 0x08, 0x10, 0x04, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00, - 0x06, 0x30, 0x20, 0x02, 0x10, 0x04, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x03, 0xE0, 0x03, 0xE0, 0x03, - 0xE0, 0x03, 0xC0, 0x07, 0xC0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x20, 0x00, 0x11, 0x40, 0x0C, - 0x10, 0x00, 0x0C, 0x20, 0x02, 0x1C, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x03, 0xE0, 0x03, 0xE0, 0x03, - 0xE0, 0x03, 0xC0, 0x07, 0xC0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x04, 0x08, 0x04, 0x10, 0x20, 0x00, 0x11, 0x40, 0x0C, - 0x10, 0x00, 0x0C, 0x20, 0x02, 0x1C, 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x01, 0x04, 0x01, 0xCC, 0x01, 0xF0, 0x03, 0xE0, 0x03, - 0xC0, 0x07, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x11, 0x04, 0x08, 0x0C, 0x04, 0x00, 0x01, 0x40, 0x20, - 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x20, 0x00, 0x60, 0x00, 0xF0, 0x00, 0xFC, 0x01, - 0xFC, 0x03, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x04, 0x20, 0x02, 0x00, 0x11, 0x40, 0x08, 0x04, 0x04, - 0x2C, 0x04, 0x00, 0x00, 0x20, 0x00, 0x18, 0x00, 0x80, 0x00, 0x40, 0x00, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x34, 0x00, 0xE0, 0x00, 0xE0, 0x03, 0xF0, 0x07, - 0xFA, 0x07, 0xE4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x88, 0x10, 0x94, 0x10, 0x00, 0x08, 0x40, 0x04, 0x00, 0x00, - 0x2A, 0x00, 0x04, 0x00, 0x80, 0x02, 0x40, 0x02, 0x20, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x14, 0x00, 0xE0, 0x01, 0xE0, 0x07, - 0xC0, 0x0F, 0xE0, 0x07, 0xE0, 0x01, 0x14, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x09, 0x88, 0x08, 0x94, 0x04, 0x00, 0x02, 0x40, 0x00, - 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x94, 0x04, 0x88, 0x08, 0x00, 0x09, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x90, 0x04, 0xE0, 0x03, 0x90, 0x06, 0xD0, 0x05, - 0xF0, 0x05, 0x20, 0x06, 0xE0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x30, 0x06, 0x10, 0x04, 0x00, 0x00, 0x0C, 0x18, - 0x0C, 0x18, 0x10, 0x00, 0x18, 0x08, 0xC8, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x40, 0x04, 0x08, 0x12, 0x91, 0x0C, 0xA2, 0x42, 0x04, 0x30, 0x80, 0x00, 0xCC, 0x19, - 0xC4, 0x11, 0x10, 0x04, 0x1A, 0x0C, 0x80, 0x00, 0x20, 0x21, 0x10, 0x46, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0A, 0x00, 0x00, 0x30, 0x06, 0x08, 0x08, 0x00, 0x00, - 0x10, 0x04, 0x04, 0x10, 0xA0, 0x02, 0x98, 0x0C, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, - 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0xE4, 0x13, 0xE0, 0x03, 0xE0, 0x03, - 0xC0, 0x01, 0xC0, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x44, 0x11, 0x10, 0x04, 0x08, 0x08, - 0x24, 0x12, 0x10, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +const unsigned short solarian_sprites[768] = /*{w:16,h:16,bpp:1,count:12,brev:1,np:4,pofs:16,sl:1,bpw:16,wpimg:64}*/ { + 0x0140, 0x0140, 0x01C0, 0x0000, 0x0000, 0x0140, 0x1144, 0x1144, + 0x1144, 0x1634, 0x1E3C, 0x1554, 0x1004, 0x1004, 0x1004, 0x1004, + 0x01C0, 0x01C0, 0x0220, 0x07F0, 0x01C0, 0x21C2, 0x21C2, 0x2BEA, + 0x3FFE, 0x3FFE, 0x3FFE, 0x3DDE, 0x3BEE, 0x3C1E, 0x280A, 0x280A, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0410, 0x0808, 0x0410, 0x0360, 0x03E0, 0x0FE0, + 0x03E0, 0x01C0, 0x01C0, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0410, 0x0808, 0x0410, 0x0000, 0x0140, 0x0018, + 0x3006, 0x0220, 0x0410, 0x180C, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0408, 0x0408, 0x0310, 0x03E0, 0x03E0, + 0x03E0, 0x07C0, 0x03C0, 0x0300, 0x0200, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0408, 0x0408, 0x2010, 0x1100, 0x0C40, + 0x0010, 0x200C, 0x1C02, 0x0020, 0x0010, 0x000C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0408, 0x0408, 0x0310, 0x03E0, 0x03E0, + 0x03E0, 0x07C0, 0x03C0, 0x0300, 0x0200, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0200, 0x0408, 0x0408, 0x2010, 0x1100, 0x0C40, + 0x0010, 0x200C, 0x1C02, 0x0020, 0x0010, 0x000C, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0180, 0x0100, 0x0104, 0x01CC, 0x03F0, 0x03E0, + 0x07C0, 0x07C0, 0x0380, 0x0200, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0180, 0x1100, 0x0804, 0x040C, 0x0100, 0x2040, + 0x1020, 0x0810, 0x0008, 0x0080, 0x0040, 0x0020, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0030, 0x0020, 0x0060, 0x00F0, 0x01FC, + 0x03FC, 0x03E0, 0x07C0, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0430, 0x0220, 0x1100, 0x0840, 0x0404, + 0x042C, 0x0000, 0x0020, 0x0018, 0x0080, 0x0040, 0x0060, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0008, 0x0034, 0x00E0, 0x03E0, 0x07F0, + 0x07FA, 0x03E4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0080, 0x0080, 0x1088, 0x1094, 0x0800, 0x0440, 0x0000, + 0x002A, 0x0004, 0x0280, 0x0240, 0x0220, 0x0200, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0008, 0x0014, 0x01E0, 0x07E0, + 0x0FC0, 0x07E0, 0x01E0, 0x0014, 0x0008, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0100, 0x0900, 0x0888, 0x0494, 0x0200, 0x0040, + 0x0000, 0x0040, 0x0200, 0x0494, 0x0888, 0x0900, 0x0100, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0808, 0x0490, 0x03E0, 0x0690, 0x05D0, + 0x05F0, 0x0620, 0x07E0, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0C18, 0x0630, 0x0410, 0x0000, 0x180C, + 0x180C, 0x0010, 0x0818, 0x09C8, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0440, 0x1208, 0x0C91, 0x42A2, 0x3004, 0x0080, 0x19CC, + 0x11C4, 0x0410, 0x0C1A, 0x0080, 0x2120, 0x4610, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0A20, 0x0000, 0x0630, 0x0808, 0x0000, + 0x0410, 0x1004, 0x02A0, 0x0C98, 0x0080, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0180, 0x0180, 0x0180, 0x0180, + 0x0180, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0180, 0x0180, 0x0180, 0x0180, + 0x0180, 0x0180, 0x0180, 0x0180, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0FF8, 0x13E4, 0x03E0, 0x03E0, + 0x01C0, 0x01C0, 0x0080, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0C18, 0x1144, 0x0410, 0x0808, + 0x1224, 0x0410, 0x0808, 0x0808, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; -const unsigned short solarian_bg_pal[16] = { 0x000, 0x1FF, 0x1C7, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; -const unsigned short solarian_spr_pal[16] = { 0x000, 0x1FF, 0x0F8, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short solarian_bg_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x1FF, 0x1C7, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; +const unsigned short solarian_spr_pal[16] = /*{pal:"pce",n:16,bpw:16}*/ { 0x000, 0x1FF, 0x0F8, 0x1F8, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000, 0x000 }; #endif