diff --git a/bb/decode.c b/bb/decode.c index 52457ef..03d9b05 100644 --- a/bb/decode.c +++ b/bb/decode.c @@ -1,7 +1,7 @@ #include "decode.h" -void decode_spr(const uint8_t *src, int src_pitch, int w, int h, int depth, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, bool amiga) { +void decode_spr(const uint8_t *src, int src_pitch, int w, int h, int depth, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, bool reverse_bitplanes) { assert((src_pitch & 7) == 0); src_pitch /= 8; assert((w & 7) == 0); @@ -15,7 +15,7 @@ void decode_spr(const uint8_t *src, int src_pitch, int w, int h, int depth, uint const int mask = 1 << (7 - i); for (int bit = 0; bit < depth; ++bit) { if (src[bit * bitplane_size] & mask) { - color |= 1 << (amiga ? bit : (3 - bit)); + color |= 1 << (reverse_bitplanes ? bit : (3 - bit)); } } dst[x * 8 + i] = color; diff --git a/bb/decode.h b/bb/decode.h index af88610..a457c88 100644 --- a/bb/decode.h +++ b/bb/decode.h @@ -4,7 +4,7 @@ #include "intern.h" -extern void decode_spr(const uint8_t *src, int src_pitch, int w, int h, int depth, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, bool amiga); +extern void decode_spr(const uint8_t *src, int src_pitch, int w, int h, int depth, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, bool reverse_bitplanes); extern void decode_amiga_blk(const uint8_t *src, uint8_t *dst, int dst_pitch); extern void decode_amiga_gfx(uint8_t *dst, int dst_pitch, int w, int h, int depth, const uint8_t *src, const int src_pitch, uint8_t palette_mask, uint16_t gfx_mask); diff --git a/bb/game.h b/bb/game.h index 88f3c18..bab0c6f 100644 --- a/bb/game.h +++ b/bb/game.h @@ -111,7 +111,7 @@ struct object_t { // int16_t unk4E; int16_t unk50; uint8_t data51; // health for obj39/40, horizontal direction for other objects - uint8_t unk53; + uint8_t scrolling_lock_flag; uint8_t unk54; uint8_t unk55; uint8_t unk56; diff --git a/bb/level.c b/bb/level.c index deb9342..2e6d0e7 100644 --- a/bb/level.c +++ b/bb/level.c @@ -248,7 +248,7 @@ static void init_level() { } obj->restart_level_flag = 0; obj->level_complete_flag = 0; - obj->unk53 = 0; + obj->scrolling_lock_flag = 0; obj->unk54 = 0; obj->unk55 = 0; obj->unk56 = 0; @@ -257,7 +257,7 @@ static void init_level() { // obj->unk5C = 1; obj->unk5D = 0; if (obj->ypos > g_vars.screen_tilemap_h) { - obj->unk53 = 1; + obj->scrolling_lock_flag = 1; } obj->blinking_counter = 0; } @@ -344,10 +344,10 @@ static void do_level_update_scrolling2() { g_vars.screen_tilemap_yorigin += 16; } } - if (!g_options.dos_scrolling) { + const struct object_t *obj = &g_vars.objects[OBJECT_NUM_PLAYER1]; + if (!g_options.dos_scrolling && !obj->scrolling_lock_flag) { const int x1 = TILEMAP_SCROLL_W * 2; const int x2 = TILEMAP_SCREEN_W - TILEMAP_SCROLL_W * 2; - const struct object_t *obj = &g_vars.objects[OBJECT_NUM_PLAYER1]; if (obj->screen_xpos > x2) { const int dx = obj->screen_xpos - x2; g_vars.screen_tilemap_xorigin += dx; @@ -1137,7 +1137,7 @@ void do_level_enter_door(struct object_t *obj) { obj->xpos = g_vars.doors[i].dst_x16 << 4; obj->ypos = g_vars.doors[i].dst_y16 << 4; if (obj->ypos > g_vars.screen_tilemap_h) { - obj->unk53 = 1; + obj->scrolling_lock_flag = 1; g_vars.screen_tilemap_yorigin = pos[g_vars.level] << 4; const int w = TILEMAP_SCREEN_W / 16; g_vars.screen_tilemap_xorigin = (((obj->xpos >> 4) / w) * w) << 4; @@ -1149,7 +1149,7 @@ void do_level_enter_door(struct object_t *obj) { } else { g_vars.screen_tilemap_yorigin += 16; } - obj->unk53 = 0; + obj->scrolling_lock_flag = 0; } obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin; obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin; @@ -1285,7 +1285,7 @@ static void do_level_update_input(struct object_t *obj) { } static void do_level_update_scrolling(struct object_t *obj) { - if (obj->unk53 != 0) { + if (obj->scrolling_lock_flag) { g_vars.screen_scrolling_dirmask = 0; return; } @@ -1538,7 +1538,7 @@ static void do_level_fixup_object_ypos16(struct object_t *obj) { obj->ypos = 32; obj->screen_ypos = 32 - g_vars.screen_tilemap_yorigin; obj->yvelocity = 0; - } else if (obj->ypos > g_vars.screen_tilemap_h && obj->unk53 == 0) { + } else if (obj->ypos > g_vars.screen_tilemap_h && !obj->scrolling_lock_flag) { obj->ypos = g_vars.screen_tilemap_h - 16; obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin; obj->yvelocity = 0; @@ -1871,10 +1871,10 @@ static void do_level_update_objects() { if (obj->type < 2) { if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player if (!g_vars.switch_player_scrolling_flag && g_vars.two_players_flag) { - if (!g_vars.player2_scrolling_flag && g_vars.objects[OBJECT_NUM_PLAYER1].unk53 == 0) { + if (!g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER1].scrolling_lock_flag) { g_vars.player2_scrolling_flag = 1; g_vars.switch_player_scrolling_flag = 1; - } else if (g_vars.player2_scrolling_flag && g_vars.objects[OBJECT_NUM_PLAYER2].unk53 == 0) { + } else if (g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER2].scrolling_lock_flag) { g_vars.player2_scrolling_flag = 1; g_vars.switch_player_scrolling_flag = 1; } diff --git a/bb/resource.c b/bb/resource.c index 2b52815..dfb8743 100644 --- a/bb/resource.c +++ b/bb/resource.c @@ -304,7 +304,6 @@ void load_m(const char *filename) { const int filesize = read_file(filename, g_res.tmp, 0); const int count = READ_BE_UINT16(g_res.tmp); assert(filesize == 2 + count * 32); - // 1-bit 16x16 mask } static int load_spr_helper(int offset, const uint8_t *ptr, uint16_t (*read16)(const uint8_t *), int depth) { diff --git a/ja/game.c b/ja/game.c index d0fca37..565aa5b 100644 --- a/ja/game.c +++ b/ja/game.c @@ -262,7 +262,7 @@ void do_game_win_screen() { fade_in_palette(); fade_out_palette(); load_file("end.eat"); - video_copy_vga(0x7D00); + video_copy_vga(0xB500); static const int count = 5; static const struct { uint16_t offset; @@ -304,7 +304,7 @@ void do_game_win_screen() { fade_in_palette(); wait_input(64000); fade_out_palette(); - video_copy_vga(0x7D00); + memcpy(g_res.tmp + 768, g_res.background, 64000); } } @@ -327,7 +327,6 @@ void game_main() { break; } else if (ret == 1) { do_select_screen(); - do_difficulty_screen(); } else if (ret == 2) { g_vars.level = -1; do_password_screen(); @@ -335,7 +334,6 @@ void game_main() { continue; } ++g_vars.level; - do_difficulty_screen(); } else { do_options_screen(); continue; diff --git a/ja/game.h b/ja/game.h index ac72506..3e58287 100644 --- a/ja/game.h +++ b/ja/game.h @@ -8,6 +8,7 @@ #define CHEATS_ONE_HIT_VINYL (1 << 1) #define CHEATS_DECOR_NO_HIT (1 << 2) #define CHEATS_UNLIMITED_VINYLS (1 << 3) +#define CHEATS_UNLIMITED_TIME (1 << 4) extern struct options_t g_options; @@ -142,7 +143,7 @@ struct vars_t { uint8_t triggers_table[19 + TRIGGERS_COUNT * 16]; int tilemap_x, tilemap_y, tilemap_w, tilemap_h; int tilemap_end_x, tilemap_end_y; - int tilemap_scroll_dx, tilemap_scroll_dy, tilemap_scroll_xoffset, tilemap_scroll_yoffset; + int tilemap_scroll_dx, tilemap_scroll_dy; uint8_t *tilemap_data; uint16_t level_pos_num; uint8_t tilemap_type, tilemap_flags; @@ -167,7 +168,11 @@ extern const uint8_t sprite_palettes[]; extern const uint8_t level_data1p[]; extern const uint8_t level_data2p[]; extern const uint8_t level_data3[]; -extern const uint8_t level_data4[]; +extern const uint8_t vscroll_offsets_table[]; +extern const uint16_t rot_tbl[]; +extern const uint8_t bonus_spr_table[]; +extern const uint8_t tiles_5dc9_lut[]; +extern const uint8_t tiles_yoffset_table[]; extern const uint8_t monster_spr_anim_data0[]; extern const uint8_t monster_spr_anim_data1[]; extern const uint8_t monster_spr_anim_data2[]; @@ -207,6 +212,7 @@ extern void video_draw_dot_pattern(int offset); extern void video_draw_sprite(int num, int x, int y, int flag); extern void video_draw_string(const char *s, int offset, int hspace); extern void video_copy_vga(int size); +extern void video_copy_backbuffer(int h); extern void fade_in_palette(); extern void fade_out_palette(); extern void ja_decode_spr(const uint8_t *src, int w, int h, uint8_t *dst, int dst_pitch, uint8_t pal_mask); diff --git a/ja/level.c b/ja/level.c index 843cd7e..44e4b82 100644 --- a/ja/level.c +++ b/ja/level.c @@ -127,11 +127,7 @@ static void level_draw_tile(uint8_t tile_num, int x, int y, int dx, int dy) { } static void level_draw_tilemap() { - for (int y = 0; y < MIN(200, GAME_SCREEN_H) - PANEL_H; ++y) { - for (int x = 0; x < GAME_SCREEN_W; x += 320) { - memcpy(g_res.vga + y * GAME_SCREEN_W + x, g_res.background + y * 320, MIN(320, GAME_SCREEN_W - x)); - } - } + video_copy_backbuffer(PANEL_H); const uint8_t *current_lut = g_vars.tilemap_current_lut + 0x100; if (current_lut >= &g_vars.tilemap_lut_init[0x600]) { g_vars.tilemap_current_lut = g_vars.tilemap_lut_init; @@ -160,10 +156,6 @@ static void level_adjust_hscroll_right(int dx) { } g_vars.tilemap_scroll_dx -= 4; ++g_vars.tilemap_x; - g_vars.tilemap_scroll_xoffset += 4; - if (g_vars.tilemap_scroll_xoffset > 84) { - g_vars.tilemap_scroll_xoffset -= 84; - } } static void level_adjust_hscroll_left(int dx) { @@ -176,12 +168,6 @@ static void level_adjust_hscroll_left(int dx) { if (g_vars.tilemap_x < 0) { g_vars.tilemap_x = 0; g_vars.tilemap_scroll_dx = 0; - g_vars.tilemap_scroll_xoffset = 0; - } else { - g_vars.tilemap_scroll_xoffset -= 4; - if (g_vars.tilemap_scroll_xoffset < 0) { - g_vars.tilemap_scroll_xoffset += 84; - } } } @@ -197,11 +183,7 @@ static void level_adjust_vscroll_down(int dy) { return; } g_vars.tilemap_scroll_dy -= 16; - ++g_vars.tilemap_scroll_yoffset; ++g_vars.tilemap_y; - if (g_vars.tilemap_scroll_yoffset >= 12) { - g_vars.tilemap_scroll_yoffset -= 12; - } } static void level_adjust_vscroll_up(int dy) { @@ -214,12 +196,6 @@ static void level_adjust_vscroll_up(int dy) { if (g_vars.tilemap_y < 0) { g_vars.tilemap_scroll_dy = 0; g_vars.tilemap_y = 0; - g_vars.tilemap_scroll_yoffset = 0; - } else { - --g_vars.tilemap_scroll_yoffset; - if (g_vars.tilemap_scroll_yoffset < 0) { - g_vars.tilemap_scroll_yoffset += 12; - } } } @@ -512,9 +488,9 @@ static void level_update_player_anim_7(struct player_t *player) { play_sound(SOUND_8); level_update_player_anim_0(player); } else { - player->obj.x_pos += 12; + player->obj.y_pos += 12; level_update_player_anim_6(player); - player->obj.x_pos -= 12; + player->obj.y_pos -= 12; } player->obj.spr_num = 7; } @@ -963,11 +939,13 @@ static void level_update_player_position() { } else { g_vars.player_xscroll += obj->x_pos - (g_vars.tilemap_x << 4) - TILEMAP_SCREEN_W / 2; } - const int y = (g_vars.tilemap_y << 4) + g_vars.tilemap_scroll_dy + 88 - obj->y_pos; + const int y = (g_vars.tilemap_y << 4) + g_vars.tilemap_scroll_dy + (TILEMAP_SCREEN_H / 2) - obj->y_pos; if (y >= 0) { - level_adjust_vscroll_up((int8_t)level_data4[0x88 + y]); + const int dy = (int8_t)vscroll_offsets_table[y]; + level_adjust_vscroll_up(dy); } else { - level_adjust_vscroll_down((int8_t)level_data4[0x88 - y]); + const int dy = (int8_t)vscroll_offsets_table[-y]; + level_adjust_vscroll_down(dy); } } @@ -1205,14 +1183,14 @@ static void level_update_object82_type0(struct object_t *obj) { } else { const int state = object82_state(obj); if (state == 0) { - const int num = object82_counter(obj) << 1; - int16_t ax1 = ((int16_t)READ_LE_UINT16(level_data4 + 0x1AE + num) * 60) >> 8; - object82_hflip(obj) = ax1 >> 8; - int16_t ax2 = ((int16_t)READ_LE_UINT16(level_data4 + 0x12C + num) * 60) >> 8; + const int angle = object82_counter(obj); + const int16_t r1 = (60 * (int16_t)rot_tbl[angle + 65]) >> 8; + object82_hflip(obj) = r1 >> 8; + const int16_t r2 = (60 * (int16_t)rot_tbl[angle]) >> 8; object82_counter(obj) += 2; const uint8_t *p = object82_type0_init_data(obj); - obj->x_pos = ax1 + READ_LE_UINT16(p); - obj->y_pos = ax2 + READ_LE_UINT16(p + 2); + obj->x_pos = r1 + READ_LE_UINT16(p); + obj->y_pos = r2 + READ_LE_UINT16(p + 2); struct player_t *player = level_get_closest_player(obj, 80); if (player) { object82_type0_player_num(obj) = player - &g_vars.players_table[0]; @@ -1518,9 +1496,10 @@ static void level_update_triggers() { object_blinking_counter(&obj[2]) = 0; obj[3].spr_num = 204; object_blinking_counter(&obj[3]) = 0; - obj->data[2].b[1] = 0x80; // rotation table index + obj->data[2].b[1] = 128; // angle obj->data[2].b[0] = 0; - obj->data[4].w = 0x3A00; // radius + obj->data[4].b[1] = 58; // radius + obj->data[4].b[0] = 0; obj->data[5].w = 8; // angle step *ptr = obj - g_vars.objects_table; obj->data[0].w = data - start; @@ -1669,7 +1648,7 @@ static void level_update_triggers() { struct object_t *obj = find_object(72, 10, 1); if (obj) { const uint16_t num = READ_LE_UINT16(data + 8); - obj->spr_num = 190 + level_data4[0x3B0 + num]; + obj->spr_num = 190 + bonus_spr_table[num]; object_blinking_counter(obj) = 0; obj->x_pos = x_pos; obj->y_pos = y_pos; @@ -1704,8 +1683,10 @@ static void level_update_triggers() { obj[0].y_pos = obj[1].y_pos = obj[2].y_pos = obj[3].y_pos = READ_LE_UINT16(_di + 2); int dx, ax = obj[0].data[1].w * 2; obj[0].data[2].w += ax; - ax = obj[0].data[4].b[1] * (int16_t)READ_LE_UINT16(level_data4 + 0x1AE + obj[0].data[2].b[1] * 2); - ax >>= 8; + const int angle = obj[0].data[2].b[1]; + const int radius = obj[0].data[4].b[1]; + + ax = (radius * (int16_t)rot_tbl[angle + 65]) >> 8; obj[0].x_pos += ax; ax >>= 1; dx = ax; @@ -1715,8 +1696,7 @@ static void level_update_triggers() { obj[3].x_pos += ax; obj[1].x_pos += dx; - ax = obj[0].data[4].b[1] * (int16_t)READ_LE_UINT16(level_data4 + 0x12C + obj[0].data[2].b[1] * 2); - ax >>= 8; + ax = (radius * (int16_t)rot_tbl[angle]) >> 8; obj[0].y_pos += ax; ax >>= 1; dx = ax; @@ -1998,7 +1978,7 @@ static void level_update_triggers() { if (level_collide_objects(obj, &g_vars.objects_table[0])) { do_end_of_level(); g_vars.change_next_level_flag = 1; - continue; + return; } } } else { @@ -2331,20 +2311,20 @@ static void level_tile_func_5dc9(struct object_t *obj, int bp) { uint8_t al; al = g_vars.tilemap_data[offset - g_vars.tilemap_w]; al = g_vars.level_tiles_lut[al]; - al = level_data4[0x3C5 + al]; + al = tiles_5dc9_lut[al]; if (al == 0) { return; } al = g_vars.tilemap_data[offset - g_vars.tilemap_w - 1]; al = g_vars.level_tiles_lut[al]; - al = level_data4[0x3C5 + al]; + al = tiles_5dc9_lut[al]; if (al == 0) { obj->x_pos -= 2; return; } al = g_vars.tilemap_data[offset - g_vars.tilemap_w + 1]; al = g_vars.level_tiles_lut[al]; - al = level_data4[0x3C5 + al]; + al = tiles_5dc9_lut[al]; if (al != 0) { if ((player_flags(obj) & 0x10) == 0) { return; @@ -2476,7 +2456,7 @@ static void level_tile_func_5f0e(struct object_t *obj, int bp) { obj->data[7].b[0] = 0; } -// sloppy tiles +// slopes static void level_tile_func_5f7b(struct object_t *obj, int bp, int bx) { if (bp != _undefined) { player_flags2(obj) &= ~0x40; @@ -2495,8 +2475,9 @@ static void level_tile_func_5f7b(struct object_t *obj, int bp, int bx) { player_jump_counter(&player->obj) = 7; player_x_delta(&player->obj) >>= 1; } - const uint8_t *p = level_data4 + 0x3F0 + ((bx - 18) << 3); - player->obj.y_pos += (int8_t)p[player->obj.x_pos & 15]; + assert(bx >= 18); + const uint8_t *p = tiles_yoffset_table + ((bx - 18) << 3); + player->obj.y_pos += p[player->obj.x_pos & 15]; } // electricity @@ -2604,7 +2585,7 @@ static void level_update_tiles(struct object_t *obj, int ax, int dx, int bp) { const int offset = (dx >> 4) * g_vars.tilemap_w + (ax >> 4); _al = level_get_tile(offset - g_vars.tilemap_w); level_tile_func(tile_funcs2[_al], obj, bp, _al * 2); - if (obj->spr_num == 3) { + if (obj->spr_num != 3) { _al = level_get_tile(offset - g_vars.tilemap_w * 2); level_tile_func(tile_funcs2[_al], obj, bp, _al * 2); } @@ -2696,7 +2677,9 @@ static void level_sync() { ++g_vars.level_time_counter; if (g_vars.level_time_counter >= 28) { g_vars.level_time_counter = 0; - --g_vars.level_time; + if ((g_options.cheats & CHEATS_UNLIMITED_TIME) == 0) { + --g_vars.level_time; + } } g_sys.update_screen(g_res.vga, 1); g_sys.render_clear_sprites(); @@ -2736,7 +2719,7 @@ static void load_level_data(uint16_t level) { dst += 2; } } - data += 7 * stride; // 14 * count + data += 7 * stride; if (g_debug_mask & DBG_GAME) { for (int i = 0; i < g_vars.triggers_table[18]; ++i) { const uint8_t *obj_data = g_vars.triggers_table + 19 + i * 16; @@ -2894,8 +2877,6 @@ static void level_init_players() { static void level_init_tilemap() { g_vars.tilemap_x = 0; g_vars.tilemap_y = 0; - g_vars.tilemap_scroll_xoffset = 0; - g_vars.tilemap_scroll_yoffset = 0; g_vars.tilemap_scroll_dx = 0; g_vars.tilemap_scroll_dy = 0; while (1) { @@ -2996,12 +2977,12 @@ static bool start_level() { } } -static bool change_level() { - if ((g_vars.level & 7) == 0 && (g_vars.level >> 3) < 4) { +static bool change_level(bool first_level) { + if (first_level || ((g_vars.level & 7) == 0 && (g_vars.level >> 3) < 4)) { do_difficulty_screen(); } if ((g_vars.level & 3) == 0 && g_vars.level < LEVELS_COUNT) { - do_level_password_screen(); + // do_level_password_screen(); } do_level_number_screen(); const int num = ((g_vars.level >> 3) & 3) + 1; @@ -3010,13 +2991,20 @@ static bool change_level() { } void do_level() { - change_level(); + change_level(true); while (!g_sys.input.quit) { g_vars.timestamp = g_sys.get_timestamp(); update_input(); level_update_palette(); level_update_input(); level_update_triggers(); + if (g_vars.change_next_level_flag) { + ++g_vars.level; + if (change_level(false)) { + continue; + } + break; + } level_update_players(); level_draw_tilemap(); draw_panel(); @@ -3025,13 +3013,6 @@ void do_level() { level_adjust_player_position(); level_sync(); ++g_vars.level_loop_counter; - if (g_vars.change_next_level_flag) { - ++g_vars.level; - if (change_level()) { - continue; - } - break; - } assert(g_vars.player != 2); if ((player_flags2(&g_vars.players_table[0].obj) & 0x10) == 0) { continue; diff --git a/ja/screen.c b/ja/screen.c index e1bdd6f..edf9d4b 100644 --- a/ja/screen.c +++ b/ja/screen.c @@ -60,6 +60,14 @@ void video_copy_vga(int size) { } } +void video_copy_backbuffer(int h) { + for (int y = 0; y < MIN(200, GAME_SCREEN_H) - h; ++y) { + for (int x = 0; x < GAME_SCREEN_W; x += 320) { + memcpy(g_res.vga + y * GAME_SCREEN_W + x, g_res.background + y * 320, MIN(320, GAME_SCREEN_W - x)); + } + } +} + void fade_in_palette() { if (!g_sys.input.quit) { g_sys.fade_in_palette(); @@ -164,7 +172,7 @@ void ja_decode_tile(const uint8_t *buffer, uint8_t pal_mask, uint8_t *dst, int d } } -static void decode_motif(const uint8_t *src, uint8_t *dst, uint8_t color) { +static void decode_motif_scanline(const uint8_t *src, uint8_t *dst, uint8_t color) { for (int x = 0; x < 40; ++x) { for (int b = 0; b < 8; ++b) { const uint8_t mask = 1 << (7 - b); @@ -180,7 +188,7 @@ void ja_decode_motif(int num, uint8_t color) { int y = 0; for (int j = 0; j < 25; ++j) { for (int i = 0; i < 8; ++i) { - decode_motif(src + i * 40 + j * 320, g_res.vga + y * GAME_SCREEN_W, color); + decode_motif_scanline(src + i * 40 + j * 320, g_res.vga + y * GAME_SCREEN_W, color); ++y; } } diff --git a/ja/staticres.c b/ja/staticres.c index cec66e9..3706f7f 100644 --- a/ja/staticres.c +++ b/ja/staticres.c @@ -82,70 +82,52 @@ const uint8_t level_data3[] = { 0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00 }; -const uint8_t level_data4[] = { - 0x2D,0x2D,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x2D,0x2D,0x2D,0x2D, - 0x41,0x2D,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x41,0x2D, - 0x44,0x46,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x43,0x2D, - 0x42,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, - 0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x37,0x38,0x39,0x2D,0x34,0x35,0x36,0x2D,0x31, - 0x32,0x33,0x30,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, - 0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, - 0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D, - 0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01, - 0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02, - 0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, - 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04, - 0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05, - 0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08, - 0x08,0x09,0x09,0x09,0x0A,0x0A,0x0B,0x0B,0x0C,0x0D,0x0E,0x10,0x10,0x10,0x10,0x10, +const uint8_t vscroll_offsets_table[] = { + 0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02, + 0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03, + 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04, + 0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06, + 0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,0x09,0x0A,0x0A,0x0B,0x0B, + 0x0C,0x0D,0x0E,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0xFF,0x01,0xFF, - 0x01,0xFF,0x01,0xFF,0x02,0xFF,0x02,0xFF,0x03,0xFF,0x04,0xFF,0x05,0xFF,0x07,0xFF, - 0x08,0xFF,0x0A,0xFF,0x0C,0xFF,0x0D,0xFF,0x0F,0xFF,0x12,0xFF,0x14,0xFF,0x16,0xFF, - 0x19,0xFF,0x1C,0xFF,0x1F,0xFF,0x22,0xFF,0x25,0xFF,0x28,0xFF,0x2C,0xFF,0x2F,0xFF, - 0x33,0xFF,0x37,0xFF,0x3B,0xFF,0x3F,0xFF,0x43,0xFF,0x47,0xFF,0x4B,0xFF,0x50,0xFF, - 0x55,0xFF,0x59,0xFF,0x5E,0xFF,0x63,0xFF,0x68,0xFF,0x6D,0xFF,0x72,0xFF,0x78,0xFF, - 0x7D,0xFF,0x82,0xFF,0x88,0xFF,0x8D,0xFF,0x93,0xFF,0x99,0xFF,0x9F,0xFF,0xA4,0xFF, - 0xAA,0xFF,0xB0,0xFF,0xB6,0xFF,0xBC,0xFF,0xC2,0xFF,0xC8,0xFF,0xCF,0xFF,0xD5,0xFF, - 0xDB,0xFF,0xE1,0xFF,0xE7,0xFF,0xEE,0xFF,0xF4,0xFF,0xFA,0xFF,0x00,0x00,0x00,0x00, - 0x06,0x00,0x0C,0x00,0x12,0x00,0x19,0x00,0x1F,0x00,0x25,0x00,0x2B,0x00,0x31,0x00, - 0x38,0x00,0x3E,0x00,0x44,0x00,0x4A,0x00,0x50,0x00,0x56,0x00,0x5C,0x00,0x61,0x00, - 0x67,0x00,0x6D,0x00,0x73,0x00,0x78,0x00,0x7E,0x00,0x83,0x00,0x88,0x00,0x8E,0x00, - 0x93,0x00,0x98,0x00,0x9D,0x00,0xA2,0x00,0xA7,0x00,0xAB,0x00,0xB0,0x00,0xB5,0x00, - 0xB9,0x00,0xBD,0x00,0xC1,0x00,0xC5,0x00,0xC9,0x00,0xCD,0x00,0xD1,0x00,0xD4,0x00, - 0xD8,0x00,0xDB,0x00,0xDE,0x00,0xE1,0x00,0xE4,0x00,0xE7,0x00,0xEA,0x00,0xEC,0x00, - 0xEE,0x00,0xF1,0x00,0xF3,0x00,0xF4,0x00,0xF6,0x00,0xF8,0x00,0xF9,0x00,0xFB,0x00, - 0xFC,0x00,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00, - 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFE,0x00,0xFE,0x00,0xFD,0x00,0xFC,0x00,0xFB,0x00, - 0xF9,0x00,0xF8,0x00,0xF6,0x00,0xF4,0x00,0xF3,0x00,0xF1,0x00,0xEE,0x00,0xEC,0x00, - 0xEA,0x00,0xE7,0x00,0xE4,0x00,0xE1,0x00,0xDE,0x00,0xDB,0x00,0xD8,0x00,0xD4,0x00, - 0xD1,0x00,0xCD,0x00,0xC9,0x00,0xC5,0x00,0xC1,0x00,0xBD,0x00,0xB9,0x00,0xB5,0x00, - 0xB0,0x00,0xAB,0x00,0xA7,0x00,0xA2,0x00,0x9D,0x00,0x98,0x00,0x93,0x00,0x8E,0x00, - 0x88,0x00,0x83,0x00,0x7E,0x00,0x78,0x00,0x73,0x00,0x6D,0x00,0x67,0x00,0x61,0x00, - 0x5C,0x00,0x56,0x00,0x50,0x00,0x4A,0x00,0x44,0x00,0x3E,0x00,0x38,0x00,0x31,0x00, - 0x2B,0x00,0x25,0x00,0x1F,0x00,0x19,0x00,0x12,0x00,0x0C,0x00,0x06,0x00,0x00,0x00, - 0xFA,0xFF,0xF4,0xFF,0xEE,0xFF,0xE7,0xFF,0xE1,0xFF,0xDB,0xFF,0xD5,0xFF,0xCF,0xFF, - 0xC8,0xFF,0xC2,0xFF,0xBC,0xFF,0xB6,0xFF,0xB0,0xFF,0xAA,0xFF,0xA4,0xFF,0x9F,0xFF, - 0x99,0xFF,0x93,0xFF,0x8D,0xFF,0x88,0xFF,0x82,0xFF,0x7D,0xFF,0x78,0xFF,0x72,0xFF, - 0x6D,0xFF,0x68,0xFF,0x63,0xFF,0x5E,0xFF,0x59,0xFF,0x55,0xFF,0x50,0xFF,0x4B,0xFF, - 0x47,0xFF,0x43,0xFF,0x3F,0xFF,0x3B,0xFF,0x37,0xFF,0x33,0xFF,0x2F,0xFF,0x2C,0xFF, - 0x28,0xFF,0x25,0xFF,0x22,0xFF,0x1F,0xFF,0x1C,0xFF,0x19,0xFF,0x16,0xFF,0x14,0xFF, - 0x12,0xFF,0x0F,0xFF,0x0D,0xFF,0x0C,0xFF,0x0A,0xFF,0x08,0xFF,0x07,0xFF,0x05,0xFF, - 0x04,0xFF,0x03,0xFF,0x02,0xFF,0x02,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF, - 0x01,0xFF,0x01,0xFF,0x01,0xFF,0x02,0xFF,0x02,0xFF,0x03,0xFF,0x04,0xFF,0x05,0xFF, - 0x07,0xFF,0x08,0xFF,0x0A,0xFF,0x0C,0xFF,0x0D,0xFF,0x0F,0xFF,0x12,0xFF,0x14,0xFF, - 0x16,0xFF,0x19,0xFF,0x1C,0xFF,0x1F,0xFF,0x22,0xFF,0x25,0xFF,0x28,0xFF,0x2C,0xFF, - 0x2F,0xFF,0x33,0xFF,0x37,0xFF,0x3B,0xFF,0x3F,0xFF,0x43,0xFF,0x47,0xFF,0x4B,0xFF, - 0x50,0xFF,0x55,0xFF,0x59,0xFF,0x5E,0xFF,0x63,0xFF,0x68,0xFF,0x6D,0xFF,0x72,0xFF, - 0x78,0xFF,0x7D,0xFF,0x82,0xFF,0x88,0xFF,0x8D,0xFF,0x93,0xFF,0x99,0xFF,0x9F,0xFF, - 0xA4,0xFF,0xAA,0xFF,0xB0,0xFF,0xB6,0xFF,0xBC,0xFF,0xC2,0xFF,0xC8,0xFF,0xCF,0xFF, - 0xD5,0xFF,0xDB,0xFF,0xE1,0xFF,0xE7,0xFF,0xEE,0xFF,0xF4,0xFF,0xFA,0xFF,0x00,0x00, + 0x10,0x10,0x10,0x10 +}; +const uint16_t rot_tbl[] = { + 0xFF01,0xFF01,0xFF01,0xFF01,0xFF02,0xFF02,0xFF03,0xFF04,0xFF05,0xFF07,0xFF08,0xFF0A,0xFF0C,0xFF0D,0xFF0F,0xFF12, + 0xFF14,0xFF16,0xFF19,0xFF1C,0xFF1F,0xFF22,0xFF25,0xFF28,0xFF2C,0xFF2F,0xFF33,0xFF37,0xFF3B,0xFF3F,0xFF43,0xFF47, + 0xFF4B,0xFF50,0xFF55,0xFF59,0xFF5E,0xFF63,0xFF68,0xFF6D,0xFF72,0xFF78,0xFF7D,0xFF82,0xFF88,0xFF8D,0xFF93,0xFF99, + 0xFF9F,0xFFA4,0xFFAA,0xFFB0,0xFFB6,0xFFBC,0xFFC2,0xFFC8,0xFFCF,0xFFD5,0xFFDB,0xFFE1,0xFFE7,0xFFEE,0xFFF4,0xFFFA, + 0x0000,0x0000,0x0006,0x000C,0x0012,0x0019,0x001F,0x0025,0x002B,0x0031,0x0038,0x003E,0x0044,0x004A,0x0050,0x0056, + 0x005C,0x0061,0x0067,0x006D,0x0073,0x0078,0x007E,0x0083,0x0088,0x008E,0x0093,0x0098,0x009D,0x00A2,0x00A7,0x00AB, + 0x00B0,0x00B5,0x00B9,0x00BD,0x00C1,0x00C5,0x00C9,0x00CD,0x00D1,0x00D4,0x00D8,0x00DB,0x00DE,0x00E1,0x00E4,0x00E7, + 0x00EA,0x00EC,0x00EE,0x00F1,0x00F3,0x00F4,0x00F6,0x00F8,0x00F9,0x00FB,0x00FC,0x00FD,0x00FE,0x00FE,0x00FF,0x00FF, + 0x00FF,0x00FF,0x00FF,0x00FF,0x00FF,0x00FE,0x00FE,0x00FD,0x00FC,0x00FB,0x00F9,0x00F8,0x00F6,0x00F4,0x00F3,0x00F1, + 0x00EE,0x00EC,0x00EA,0x00E7,0x00E4,0x00E1,0x00DE,0x00DB,0x00D8,0x00D4,0x00D1,0x00CD,0x00C9,0x00C5,0x00C1,0x00BD, + 0x00B9,0x00B5,0x00B0,0x00AB,0x00A7,0x00A2,0x009D,0x0098,0x0093,0x008E,0x0088,0x0083,0x007E,0x0078,0x0073,0x006D, + 0x0067,0x0061,0x005C,0x0056,0x0050,0x004A,0x0044,0x003E,0x0038,0x0031,0x002B,0x0025,0x001F,0x0019,0x0012,0x000C, + 0x0006,0x0000,0xFFFA,0xFFF4,0xFFEE,0xFFE7,0xFFE1,0xFFDB,0xFFD5,0xFFCF,0xFFC8,0xFFC2,0xFFBC,0xFFB6,0xFFB0,0xFFAA, + 0xFFA4,0xFF9F,0xFF99,0xFF93,0xFF8D,0xFF88,0xFF82,0xFF7D,0xFF78,0xFF72,0xFF6D,0xFF68,0xFF63,0xFF5E,0xFF59,0xFF55, + 0xFF50,0xFF4B,0xFF47,0xFF43,0xFF3F,0xFF3B,0xFF37,0xFF33,0xFF2F,0xFF2C,0xFF28,0xFF25,0xFF22,0xFF1F,0xFF1C,0xFF19, + 0xFF16,0xFF14,0xFF12,0xFF0F,0xFF0D,0xFF0C,0xFF0A,0xFF08,0xFF07,0xFF05,0xFF04,0xFF03,0xFF02,0xFF02,0xFF01,0xFF01, + 0xFF01,0xFF01,0xFF01,0xFF01,0xFF01,0xFF02,0xFF02,0xFF03,0xFF04,0xFF05,0xFF07,0xFF08,0xFF0A,0xFF0C,0xFF0D,0xFF0F, + 0xFF12,0xFF14,0xFF16,0xFF19,0xFF1C,0xFF1F,0xFF22,0xFF25,0xFF28,0xFF2C,0xFF2F,0xFF33,0xFF37,0xFF3B,0xFF3F,0xFF43, + 0xFF47,0xFF4B,0xFF50,0xFF55,0xFF59,0xFF5E,0xFF63,0xFF68,0xFF6D,0xFF72,0xFF78,0xFF7D,0xFF82,0xFF88,0xFF8D,0xFF93, + 0xFF99,0xFF9F,0xFFA4,0xFFAA,0xFFB0,0xFFB6,0xFFBC,0xFFC2,0xFFC8,0xFFCF,0xFFD5,0xFFDB,0xFFE1,0xFFE7,0xFFEE,0xFFF4, + 0xFFFA,0x0000 +}; +const uint8_t bonus_spr_table[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04, - 0x05,0x00,0x06,0x00,0x07,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01, + 0x05,0x00,0x06,0x00,0x07 +}; +const uint8_t tiles_5dc9_lut[] = { + 0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,0x01,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,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01, + 0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01 +}; +const uint8_t tiles_yoffset_table[] = { 0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00, 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, @@ -169,93 +151,7 @@ const uint8_t level_data4[] = { 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0F,0x0F,0x0F,0x0E, 0x0E,0x0E,0x0D,0x0D,0x0D,0x0C,0x0C,0x0C,0x0B,0x0B,0x0B,0x0A,0x0A,0x0A,0x09,0x09, 0x09,0x09,0x0A,0x0A,0x0A,0x0B,0x0B,0x0B,0x0C,0x0C,0x0C,0x0D,0x0D,0x0D,0x0E,0x0E, - 0x0E,0x0F,0x0F,0x0F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10, - 0x00,0x00,0x00,0x00,0x00,0x1D,0x1E,0x00,0x04,0x01,0x01,0x01,0x00,0x00,0x00,0x0B, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x1B,0x05,0x00,0x05,0x00,0x01,0x01, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x00,0x07, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x05,0x1C,0x1A,0x05,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,0x01,0x00,0x00, - 0x00,0x0B,0x0C,0x0D,0x0E,0x0F,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x00,0x00, - 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x1F,0x20,0x00,0x00,0x1D,0x1E,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1A, - 0x19,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x06,0x06,0x06,0x06,0x06, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02, - 0x02,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,0x02,0x02,0x00,0x00,0x00,0x00, - 0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02, - 0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00, - 0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0A,0x0A,0x0A,0x02,0x02,0x00,0x00,0x21,0x22,0x21,0x22,0x0A, - 0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x02,0x02,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00, - 0x01,0x01,0x08,0x01,0x01,0x26,0x26,0x26,0x27,0x27,0x27,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09, - 0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06, - 0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x08,0x01,0x02,0x02,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x23,0x23,0x00,0x08,0x00,0x01,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02, - 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x23,0x23,0x02,0x08,0x02,0x02,0x00, - 0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x23,0x08, - 0x08,0x02,0x02,0x00,0x00,0x02,0x00,0x00,0x23,0x23,0x23,0x23,0x00,0x00,0x00,0x00, - 0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28, - 0x00,0x00,0x08,0x00,0x02,0x02,0x00,0x23,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x08, - 0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x08,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06, - 0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21, - 0x22,0x21,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x02,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x23,0x23,0x23,0x23,0x23,0x23, - 0x23,0x23,0x23,0x23,0x02,0x02,0x02,0x02,0x23,0x00,0x00,0x00,0x00,0x02,0x02,0x02, - 0x02,0x02,0x02,0x02,0x23,0x02,0x02,0x02,0x02,0x02,0x23,0x02,0x23,0x00,0x00,0x00, - 0x02,0x02,0x23,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06, - 0xAA,0x5D,0x83,0x5E,0x83,0x5E,0xAA,0x5D,0x73,0x5F,0xAA,0x5D,0xAA,0x5D,0x78,0x5F, - 0xAA,0x5D,0x83,0x5E,0x83,0x5E,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x0E,0x5F,0x0E,0x5F,0x83,0x5E,0xAA,0x5D,0xAA,0x5D,0xAA,0x5D,0xAA,0x5D, - 0xAA,0x5D,0xAA,0x5D,0x0E,0x5F,0xAA,0x5D,0x83,0x5E,0x83,0x5E,0xAA,0x5D,0x73,0x5F, - 0xAA,0x5D,0xEC,0x5E,0x78,0x5F,0x3E,0x5D,0x83,0x5E,0x83,0x5E,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x16,0x5F,0x16,0x5F,0xA7,0x5F,0x94,0x5F, - 0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x0E,0x5F,0xC8,0x5D,0xC8,0x5D, - 0xC9,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC9,0x5D, - 0xC9,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D, - 0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D, - 0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D, - 0xC8,0x5D,0x9E,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F, - 0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0x58,0x5E,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D, - 0xC8,0x5D,0xC8,0x5D,0x58,0x5E,0x58,0x5E,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F, - 0x7B,0x5F,0x7B,0x5F,0xC8,0x5D,0xC8,0x5D,0x9E,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F, - 0x94,0x5F,0x94,0x5F,0x94,0x5F,0xC8,0x5D + 0x0E,0x0F,0x0F,0x0F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10 }; const uint8_t monster_spr_anim_data0[] = { 0xE6,0x00,0xFF,0xFF diff --git a/sys_sdl2.c b/sys_sdl2.c index 762a3ae..86cab35 100644 --- a/sys_sdl2.c +++ b/sys_sdl2.c @@ -39,6 +39,7 @@ static struct input_t *_input = &g_sys.input; static int _copper_color; static uint32_t _copper_palette[COPPER_BARS_H]; static SDL_GameController *_controller; +static SDL_Joystick *_joystick; static int sdl2_init() { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); @@ -64,6 +65,12 @@ static int sdl2_init() { } } } + if (!_controller) { + _joystick = SDL_JoystickOpen(0); + if (_joystick) { + fprintf(stdout, "Using joystick '%s'\n", SDL_JoystickName(_joystick)); + } + } } return 0; } @@ -90,6 +97,10 @@ static void sdl2_fini() { SDL_GameControllerClose(_controller); _controller = 0; } + if (_joystick) { + SDL_JoystickClose(_joystick); + _joystick = 0; + } SDL_Quit(); } @@ -420,6 +431,50 @@ static void handle_controllerbutton(int button, bool pressed) { } } +static void handle_joystickhatmotion(int value) { + _input->direction = 0; + if (value & SDL_HAT_UP) { + _input->direction |= INPUT_DIRECTION_UP; + } + if (value & SDL_HAT_DOWN) { + _input->direction |= INPUT_DIRECTION_DOWN; + } + if (value & SDL_HAT_LEFT) { + _input->direction |= INPUT_DIRECTION_LEFT; + } + if (value & SDL_HAT_RIGHT) { + _input->direction |= INPUT_DIRECTION_RIGHT; + } +} + +static void handle_joystickaxismotion(int axis, int value) { + static const int THRESHOLD = 3200; + switch (axis) { + case 0: + _input->direction &= ~(INPUT_DIRECTION_RIGHT | INPUT_DIRECTION_LEFT); + if (value > THRESHOLD) { + _input->direction |= INPUT_DIRECTION_RIGHT; + } else if (value < -THRESHOLD) { + _input->direction |= INPUT_DIRECTION_LEFT; + } + break; + case 1: + _input->direction &= ~(INPUT_DIRECTION_UP | INPUT_DIRECTION_DOWN); + if (value > THRESHOLD) { + _input->direction |= INPUT_DIRECTION_DOWN; + } else if (value < -THRESHOLD) { + _input->direction |= INPUT_DIRECTION_UP; + } + break; + } +} + +static void handle_joystickbutton(int button, int pressed) { + if (button == 0) { + _input->space = pressed; + } +} + static int handle_event(const SDL_Event *ev) { switch (ev->type) { case SDL_QUIT: @@ -461,6 +516,26 @@ static int handle_event(const SDL_Event *ev) { handle_controlleraxis(ev->caxis.axis, ev->caxis.value); } break; + case SDL_JOYHATMOTION: + if (_joystick) { + handle_joystickhatmotion(ev->jhat.value); + } + break; + case SDL_JOYAXISMOTION: + if (_joystick) { + handle_joystickaxismotion(ev->jaxis.axis, ev->jaxis.value); + } + break; + case SDL_JOYBUTTONUP: + if (_joystick) { + handle_joystickbutton(ev->jbutton.button, 0); + } + break; + case SDL_JOYBUTTONDOWN: + if (_joystick) { + handle_joystickbutton(ev->jbutton.button, 1); + } + break; default: return -1; }