From 140c6cdb1e7d86929f2a18f7af4312b8ce1f89c2 Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Sun, 13 Mar 2022 06:26:29 +0800 Subject: [PATCH] Import blues from 3ac3f56f --- intern.h | 3 +- ja/level.c | 13 ++- ja/screen.c | 7 +- main.c | 4 +- p2/bosses.c | 6 +- p2/game.c | 56 ++++++++++-- p2/game.h | 11 ++- p2/level.c | 225 +++++++++++++++++++++++++++++++++++++------------ p2/screen.c | 13 +++ p2/staticres.c | 22 +++++ sys.h | 2 +- sys_sdl2.c | 32 ++++--- 12 files changed, 306 insertions(+), 88 deletions(-) diff --git a/intern.h b/intern.h index 331a420..6dc8b56 100644 --- a/intern.h +++ b/intern.h @@ -50,12 +50,13 @@ struct options_t { int start_ypos16; int screen_w; int screen_h; + bool dos_scrolling; // 'bb' only options bool amiga_copper_bars; bool amiga_colors; bool amiga_status_bar; - bool dos_scrolling; bool cga_colors; + // 'p2' only options bool hybrid_color; }; diff --git a/ja/level.c b/ja/level.c index e3b101a..1d0831b 100644 --- a/ja/level.c +++ b/ja/level.c @@ -135,9 +135,16 @@ static void level_draw_tilemap() { g_vars.tilemap_current_lut = current_lut; } for (int y = 0; y < TILEMAP_SCREEN_H / 16 + 1; ++y) { + const int y_offset = g_vars.tilemap_y + y; + if (!(y_offset >= 0 && y_offset < g_vars.tilemap_h)) { + continue; + } for (int x = 0; x < TILEMAP_SCREEN_W / 16 + 1; ++x) { - const int offset = (g_vars.tilemap_y + y) * g_vars.tilemap_w + (g_vars.tilemap_x + x); - const uint8_t num = g_vars.tilemap_data[offset]; + const int x_offset = g_vars.tilemap_x + x; + if (!(x_offset >= 0 && x_offset < g_vars.tilemap_w)) { + continue; + } + const uint8_t num = g_vars.tilemap_data[y_offset * g_vars.tilemap_w + x_offset]; level_draw_tile(num, x, y, g_vars.tilemap_scroll_dx << 2, g_vars.tilemap_scroll_dy); } } @@ -2925,6 +2932,7 @@ static void level_player_draw_powerdown_animation(struct player_t *player) { }; for (int i = 0; data[i] != 0xFF; ++i) { level_draw_tilemap(); + draw_panel(); level_draw_objects(); level_sync(); player_obj->spr_num = data[i]; @@ -2953,6 +2961,7 @@ static void level_player_draw_powerup_animation(struct player_t *player, struct struct object_t *player_obj = &g_vars.objects_table[player_obj_num(&player->obj)]; for (int i = 0; data[i] != 0xFF; ++i) { level_draw_tilemap(); + draw_panel(); level_draw_objects(); level_sync(); player_obj->spr_num = data[i]; diff --git a/ja/screen.c b/ja/screen.c index b795a0b..025f097 100644 --- a/ja/screen.c +++ b/ja/screen.c @@ -61,11 +61,16 @@ void video_copy_vga(int size) { } void video_copy_backbuffer(int h) { - for (int y = 0; y < MIN(200, GAME_SCREEN_H) - h; ++y) { + int y = 0; + for (; 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)); } } + h = GAME_SCREEN_H - y; + if (h > 0) { + memset(g_res.vga + y * GAME_SCREEN_W, 0, GAME_SCREEN_W * h); + } } 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/main.c b/main.c index f812c42..688b537 100644 --- a/main.c +++ b/main.c @@ -55,11 +55,11 @@ int main(int argc, char *argv[]) { g_options.start_ypos16 = -1; g_options.screen_w = 320; g_options.screen_h = 200; + g_options.dos_scrolling = false; g_options.amiga_copper_bars = true; g_options.amiga_colors = true; // g_options.amiga_status_bar = true; g_options.cga_colors = false; - g_options.dos_scrolling = false; g_options.hybrid_color = false; const char *data_path = DEFAULT_DATA_PATH; int scale_factor = DEFAULT_SCALE_FACTOR; @@ -143,7 +143,7 @@ int main(int argc, char *argv[]) { fprintf(stdout, "No data files found\n"); } else { g_sys.init(); - g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, game->name, scale_factor, scale_filter, fullscreen, g_options.hybrid_color); + g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, game->name, scale_factor, scale_filter, fullscreen); game->run(data_path); g_sys.fini(); } diff --git a/p2/bosses.c b/p2/bosses.c index 4102545..fbba95d 100644 --- a/p2/bosses.c +++ b/p2/bosses.c @@ -193,7 +193,7 @@ static void level_update_boss_gorilla_helper2() { for (int j = 103; j <= 107; ++j) { g_vars.objects_tbl[j].spr_num |= 0x4000; } - g_vars.player_flying_flag = 0; + g_vars.player_flying_flag = false; level_update_boss_gorilla_tick(); g_res.level.boss_energy -= g_vars.player_club_power; if (g_res.level.boss_energy < 0) { @@ -651,9 +651,9 @@ static void level_update_boss_tree() { if (_di->spr_num == 0xFFFF || _di == obj_player) { continue; } - g_vars.player_using_club_flag = 1; + g_vars.player_using_club_flag = true; const bool ret = level_objects_collide(_si, _di); - g_vars.player_using_club_flag = 0; + g_vars.player_using_club_flag = false; if (ret) { _si->spr_num ^= 0x4000; if (g_vars.boss_level5.state != 0) { diff --git a/p2/game.c b/p2/game.c index e5c1147..7f487ce 100644 --- a/p2/game.c +++ b/p2/game.c @@ -112,19 +112,18 @@ static bool fade_palettes(const uint8_t *target, uint8_t *current) { bool flag = false; for (int i = 0; i < 768; ++i) { int al = current[i]; - const int bh = target[i] - al; - if (bh != 0) { - if (abs(bh) < 2) { + const int diff = target[i] - al; + if (diff != 0) { + if (abs(diff) < 2) { flag = true; - al = target[i]; + current[i] = target[i]; } else { if (target[i] < al) { - al -= 2; + current[i] = al - 2; } else { - al += 2; + current[i] = al + 2; } } - current[i] = al; } } return flag; @@ -184,7 +183,38 @@ static void do_castle_screen() { } } -static void do_menu() { +void do_gameover_animation(); + +void do_gameover_screen() { + uint8_t *data = load_file("GAMEOVER.SQZ"); + if (data) { + video_copy_img(data); + video_copy_background(); + g_sys.update_screen(g_res.vga, 0); + g_sys.set_screen_palette(gameover_palette_data, 0, 16, 6); + do_gameover_animation(); + g_sys.fade_out_palette(); + free(data); + } +} + +void do_demo_animation(); + +static void do_menu2() { + uint8_t *data = load_file("MENU2.SQZ"); + if (data) { + video_copy_img(data); + video_copy_background(); + g_sys.update_screen(g_res.vga, 0); + g_sys.set_screen_palette(data + 32000, 0, 16, 6); + g_sys.fade_in_palette(); + do_demo_animation(); + g_sys.fade_out_palette(); + free(data); + } +} + +static bool do_menu() { uint8_t *data = load_file("MENU.SQZ"); if (data) { g_sys.set_screen_palette(data, 0, 256, 6); @@ -192,6 +222,7 @@ static void do_menu() { g_sys.fade_in_palette(); free(data); memset(g_vars.input.keystate, 0, sizeof(g_vars.input.keystate)); + const uint32_t start = g_sys.get_timestamp(); while (!g_sys.input.quit) { update_input(); if (g_vars.input.keystate[2] || g_vars.input.keystate[0x4F] || g_sys.input.space) { @@ -204,8 +235,13 @@ static void do_menu() { break; } g_sys.sleep(30); + if (!g_res.dos_demo && g_sys.get_timestamp() - start >= 15 * 1000) { + g_sys.fade_out_palette(); + return true; + } } } + return false; } static void do_photos_screen() { @@ -312,7 +348,9 @@ static void game_run(const char *data_path) { if (g_res.dos_demo) { do_demo_screen(); } - do_menu(); + while (do_menu()) { + do_menu2(); + } if (g_sys.input.quit) { break; } diff --git a/p2/game.h b/p2/game.h index 0a4c517..d736967 100644 --- a/p2/game.h +++ b/p2/game.h @@ -146,13 +146,13 @@ struct vars_t { uint8_t player_lifes; int8_t player_energy; uint8_t player_death_flag; - uint8_t player_flying_flag; + bool player_flying_flag; uint8_t player_flying_counter; uint8_t player_flying_anim_index; uint8_t player_bonus_letters_mask; uint8_t player_utensils_mask; uint8_t player_gravity_flag; /* 0, 1 or 2 */ - uint8_t player_unk_counter1; + uint8_t player_runup_counter; uint8_t player_moving_counter; uint8_t player_anim_0x40_flag; uint8_t player_anim2_counter; @@ -287,6 +287,7 @@ extern const uint8_t credits_palette_data[16 * 3]; extern const uint8_t light_palette_data[16 * 3]; extern const uint8_t present_palette_data[256 * 3]; extern const uint8_t menu_palette_data[16 * 3]; +extern const uint8_t gameover_palette_data[16 * 3]; extern const uint8_t spr_offs_tbl[922]; extern const uint8_t spr_size_tbl[922]; extern const uint16_t score_tbl[17]; @@ -305,12 +306,17 @@ extern const uint16_t boss_gorilla_data[19 * 10]; extern const uint16_t boss_gorilla_spr_tbl[46 * 3]; /* uint16_t: spr1_num, uint16_t: spr2_num, int8_t: dx, int8_t: dy */ extern const uint16_t snow_pattern1_data[1]; extern const uint16_t snow_pattern2_data[10]; +extern const uint8_t demo_anim_data[26]; +extern const uint8_t gameover_anim1_data[18]; +extern const uint8_t gameover_anim2_data[34]; +extern const uint8_t gameover_anim3_data[20]; /* game.c */ extern void update_input(); extern void input_check_ctrl_alt_e(); extern void input_check_ctrl_alt_w(); extern void do_theend_screen(); +extern void do_gameover_screen(); extern uint32_t timer_get_counter(); extern void random_reset(); extern uint8_t random_get_number(); @@ -334,6 +340,7 @@ extern void monster_change_prev_anim(struct object_t *obj); extern void video_draw_string(int offset, int hspace, const char *s); extern void video_clear(); extern void video_copy_img(const uint8_t *src); +extern void video_copy_background(); extern void video_draw_panel(const uint8_t *src); extern void video_draw_panel_number(int offset, int num); extern void video_draw_number(int offset, int num); diff --git a/p2/level.c b/p2/level.c index defa8e9..69c7be7 100644 --- a/p2/level.c +++ b/p2/level.c @@ -23,6 +23,14 @@ static void level_player_death_animation(); static const uint8_t next_level_tbl[] = { 0xFF, 0x0C, 0x0B, 0x0A, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x0E }; static void set_level_palette() { + if (g_options.hybrid_color && g_vars.level_num == 2) { + uint8_t palette[16 * 3]; + memcpy(palette, palettes_tbl[2], 16 * 3); + palette[4] = 0x05; + palette[5] = 0x32; + g_sys.set_screen_palette(palette, 0, 16, 6); + return; + } g_sys.set_screen_palette(palettes_tbl[g_vars.level_num], 0, 16, 6); } @@ -320,16 +328,7 @@ static void level_update_tilemap() { return; } } - if (GAME_SCREEN_W * GAME_SCREEN_H == 64000) { - memcpy(g_res.vga, g_res.background, 320 * 200); - } else { - memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); - for (int y = 0; y < MIN(200, GAME_SCREEN_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_background(); g_vars.tile_attr2_flags = 0; uint16_t offset = (g_vars.tilemap.y << 8) | g_vars.tilemap.x; for (int y = 0; y < (TILEMAP_SCREEN_H / 16) + 1; ++y) { @@ -383,13 +382,13 @@ static bool level_adjust_hscroll_left() { } static uint16_t tilemap_end_xpos() { - int end_x = (g_vars.objects_tbl[1].x_pos >> 4) - (TILEMAP_SCREEN_W / 16); - if (g_res.level.tilemap_w < end_x) { - end_x = 256 - (TILEMAP_SCREEN_W / 16); + int x; + if ((g_vars.objects_tbl[1].x_pos >> 4) > g_res.level.tilemap_w + 20) { + x = 256; /* gate */ } else { - end_x = g_res.level.tilemap_w; + x = g_res.level.tilemap_w + 20; } - return end_x; + return x - (TILEMAP_SCREEN_W / 16); } static bool level_adjust_hscroll_right() { @@ -562,7 +561,7 @@ static void level_adjust_y_scroll() { if (index >= 0 && index < 132) { dl = vscroll_offsets_data[index]; } else { - print_warning("Invalid scroll down delta %d", index); + print_debug(DBG_GAME, "Invalid scroll down delta %d", index); return; } } @@ -579,7 +578,7 @@ static void level_adjust_y_scroll() { if (index >= 0 && index < 132) { dl = vscroll_offsets_data[index]; } else { - print_warning("Invalid scroll up delta %d", index); + print_debug(DBG_GAME, "Invalid scroll up delta %d", index); return; } } @@ -991,7 +990,7 @@ static void level_reset() { g_vars.level_completed_flag = 0; g_vars.light.palette_flag1 = 0; g_vars.light.palette_flag2 = 0; - g_vars.player_flying_flag = 0; + g_vars.player_flying_flag = false; g_vars.player_gravity_flag = 0; g_vars.objects_tbl[1].data.p.special_anim_num = 0; @@ -1132,7 +1131,7 @@ bool level_objects_collide(const struct object_t *si, const struct object_t *di) if (a >= d) { return false; } - if (g_vars.player_using_club_flag == 0) { + if (!g_vars.player_using_club_flag) { d -= a; if (g_vars.objects_tbl[1].data.p.y_velocity >= 128 || (d <= (b >> 1) && si != &g_vars.objects_tbl[1])) { ++g_vars.player_jump_monster_flag; @@ -1146,7 +1145,7 @@ bool level_objects_collide(const struct object_t *si, const struct object_t *di) SWAP(a, d); b = spr_size_tbl[(si->spr_num & 0x1FFF) * 2]; } - if (g_vars.player_using_club_flag == 0) { + if (!g_vars.player_using_club_flag) { b >>= 1; } return (a + b > d); @@ -1409,7 +1408,7 @@ static void level_update_objects_axe() { continue; } } - if (g_vars.player_flying_flag == 0) { + if (!g_vars.player_flying_flag) { struct object_t *obj = &g_vars.objects_tbl[0]; if (obj->spr_num != 0xFFFF) { if (level_collide_axe_monsters(obj) || level_collide_axe_bonuses(obj)) { @@ -1941,7 +1940,7 @@ static void level_update_player_jump() { level_update_player_hdir_x_velocity(80); level_update_player_y_velocity(192); uint8_t num; - if (g_vars.player_flying_flag != 0) { + if (g_vars.player_flying_flag) { num = 45; if (g_vars.objects_tbl[1].data.p.y_velocity >= 0) { ++num; @@ -2087,7 +2086,7 @@ static void level_update_player_anim_0(uint8_t al) { level_update_player_anim_3_6_7(g_vars.objects_tbl[1].data.p.current_anim_num); return; } - g_vars.player_unk_counter1 = 0; + g_vars.player_runup_counter = 0; level_update_screen_x_velocity(); level_update_player_x_velocity(); if (g_vars.level_force_x_scroll_flag == 0 && g_vars.objects_tbl[1].data.p.y_velocity != 0) { @@ -2170,11 +2169,11 @@ static void level_update_player_anim_1(uint8_t al) { return; } const int x_vel = abs(g_vars.objects_tbl[1].x_velocity); - if (x_vel >= 64 && g_vars.player_flying_flag != 0) { - if (g_vars.player_unk_counter1 < UCHAR_MAX) { - ++g_vars.player_unk_counter1; + if (x_vel >= 64 && g_vars.player_flying_flag) { + if (g_vars.player_runup_counter < UCHAR_MAX) { + ++g_vars.player_runup_counter; } - if (g_vars.player_unk_counter1 == 23) { + if (g_vars.player_runup_counter == 23) { level_init_object_hit_from_player_pos(); } } @@ -2194,7 +2193,7 @@ static void level_update_player_anim_2_helper(uint8_t al) { if (value < 9) { static const int8_t y_tbl[] = { -65, -51, -35, -20, -10, -5, -2, -1, 0 }; int16_t ax = y_tbl[value]; - if (g_vars.player_flying_flag != 0) { + if (g_vars.player_flying_flag) { ax >>= 1; } g_vars.objects_tbl[1].data.p.y_velocity += ax; @@ -2251,7 +2250,7 @@ static void level_update_player_anim_5(uint8_t al) { level_update_player_anim_3_6_7(g_vars.objects_tbl[1].data.p.current_anim_num); return; } - g_vars.player_unk_counter1 = 0; + g_vars.player_runup_counter = 0; g_vars.player_action_counter = 4; level_update_player_club_power(); const uint8_t *p = level_update_player_anim2_num(al, al * 2); @@ -2268,13 +2267,13 @@ static void level_update_player_anim_8(uint8_t al) { } static void level_update_player_anim_34(uint8_t al) { - if (g_vars.player_unk_counter1 < 24) { + if (g_vars.player_runup_counter < 24) { level_update_player_anim_2_helper(al); } else { g_vars.player_gravity_flag = 1; g_vars.player_flying_counter = 24; g_vars.objects_tbl[1].y_pos -= 3; - g_vars.player_unk_counter1 = 0; + g_vars.player_runup_counter = 0; level_update_screen_x_velocity(); level_update_screen_x_velocity(); } @@ -2338,15 +2337,15 @@ static void level_update_player_decor() { } static void level_update_player_flying() { - if (g_vars.player_flying_flag == 0) { + if (!g_vars.player_flying_flag) { return; } if (g_vars.player_gravity_flag != 0) { const int x_vel = abs(g_vars.objects_tbl[1].x_velocity); int num = 48; - if (x_vel < 64) { + if (x_vel <= 64) { ++num; - if (x_vel < 32) { + if (x_vel <= 32) { ++num; } } @@ -2377,7 +2376,7 @@ static void level_update_player_flying() { spr_num |= 0x8000; x_delta = -x_delta; } - if (g_vars.player_unk_counter1 > 24 && (spr_num & 0x1FFF) < 121) { + if (g_vars.player_runup_counter > 24 && (spr_num & 0x1FFF) < 121) { ++spr_num; } g_vars.objects_tbl[0].spr_num = spr_num; @@ -2468,13 +2467,13 @@ static void level_update_player() { if (g_vars.player_update_counter < USHRT_MAX) { ++g_vars.player_update_counter; } - if (g_vars.player_flying_flag != 0) { + if (g_vars.player_flying_flag) { al += 0x20; if ((g_vars.player_gravity_flag &= 1) != 0) { if (g_vars.input.key_up) { if (g_vars.player_flying_anim_index == 6) { if (g_vars.objects_tbl[1].data.p.y_velocity > 16) { - g_vars.player_flying_flag |= 2; + g_vars.player_gravity_flag |= 2; } } else { ++g_vars.player_flying_anim_index; @@ -2496,7 +2495,7 @@ static void level_update_player() { if (g_vars.player_flying_anim_index != 0) { --g_vars.player_flying_anim_index; } - g_vars.player_flying_flag |= 2; + g_vars.player_gravity_flag |= 2; if (g_vars.player_flying_anim_index <= 1) { const int x = abs(g_vars.objects_tbl[1].x_velocity >> 4); if (g_vars.player_flying_counter < x * 5) { @@ -2641,8 +2640,8 @@ static void level_update_player_collision() { g_vars.objects_tbl[1].data.p.y_velocity = -128; g_vars.objects_tbl[1].x_velocity = -(g_vars.objects_tbl[1].x_velocity << 2); g_vars.player_gravity_flag = 0; - if (g_vars.player_flying_flag != 0) { - g_vars.player_flying_flag = 0; + if (g_vars.player_flying_flag) { + g_vars.player_flying_flag = false; } else { if ((g_options.cheats & CHEATS_UNLIMITED_ENERGY) == 0) { --g_vars.player_energy; @@ -2813,8 +2812,8 @@ static void level_update_player_collision() { } } else if (num <= 74) { play_sound(8); - if (g_vars.player_flying_flag == 0) { - g_vars.player_flying_flag = 1; + if (!g_vars.player_flying_flag) { + g_vars.player_flying_flag = true; g_vars.objects_tbl[1].data.p.current_anim_num = 0xFF; level_clear_item(obj); } @@ -2931,11 +2930,11 @@ static void level_update_objects_items() { continue; } const int16_t x = (level_item->x_pos >> 4) - g_vars.tilemap.x; - if (x < 0 || x > 22) { + if (x < 0 || x > MAX(22, TILEMAP_SCREEN_W / 16 + 1)) { continue; } const int16_t y = (level_item->y_pos >> 4) - g_vars.tilemap.y; - if (y < 0 || y > 43) { + if (y < 0 || y > MAX(43, TILEMAP_SCREEN_H / 16 + 1)) { continue; } obj->x_pos = level_item->x_pos; @@ -2967,7 +2966,7 @@ static void level_update_gates() { if (g_vars.player_action_counter == 0) { return; } - if (g_vars.player_flying_flag != 0) { + if (g_vars.player_flying_flag) { return; } uint16_t pos = level_get_player_tile_pos(); @@ -3158,6 +3157,9 @@ static bool level_update_objects_anim() { } input_check_ctrl_alt_e(); play_music(17); + if (!g_res.dos_demo) { + do_gameover_screen(); + } g_vars.objects_tbl[1].spr_num = 13; g_vars.level_num = 0; g_vars.score = 0; @@ -3284,6 +3286,7 @@ static void level_draw_objects() { if (obj->hit_counter != 0) { --obj->hit_counter; } + print_debug(DBG_GAME, "draw obj %d counter %d spr_num %d x_pos %d y_pos %d", i, obj->hit_counter, obj->spr_num, obj->x_pos, obj->y_pos); if (obj->hit_counter != 0 && (g_vars.level_draw_counter & 3) != 0) { continue; } @@ -3293,6 +3296,7 @@ static void level_draw_objects() { int spr_h = spr_size_tbl[2 * spr_num + 1]; spr_y_pos -= spr_h; if (spr_y_pos > TILEMAP_SCREEN_H || spr_y_pos + spr_h < 0) { + print_debug(DBG_GAME, "spr_y_pos > TILEMAP_SCREEN_H"); continue; } int spr_x_pos = obj->x_pos - ((g_vars.tilemap.x << 4) + g_vars.tilemap.scroll_dx); @@ -3302,6 +3306,7 @@ static void level_draw_objects() { } spr_x_pos -= spr_w; if (spr_x_pos > TILEMAP_SCREEN_W || spr_x_pos + spr_w < 0) { + print_debug(DBG_GAME, "spr_x_pos > TILEMAP_SCREEN_W"); continue; } video_draw_sprite(spr_num, spr_x_pos, spr_y_pos, spr_hflip); @@ -3579,7 +3584,7 @@ static void level_completed_bonuses_animation() { g_vars.objects_tbl[1].data.p.hdir = 0; g_vars.objects_tbl[1].x_velocity = 0; level_completed_bonuses_animation_draw_score(); - g_vars.player_flying_flag = 0; + g_vars.player_flying_flag = false; g_vars.objects_tbl[1].data.p.anim = object_anim_tbl[1]; while (1) { level_update_object_anim(g_vars.objects_tbl[1].data.p.anim); @@ -3733,27 +3738,32 @@ static void update_object_demo_animation(struct object_t *obj) { } int spr_num = (num & 0x1FFF) + g_res.spr_monsters_offset; if (obj->data.m.x_velocity < 0) { - num |= 0x8000; + spr_num |= 0x8000; } obj->spr_num = spr_num; obj->data.m.anim = p + 2; } void do_demo_animation() { + memset(&g_vars.objects_tbl[0], 0, sizeof(struct object_t) * OBJECTS_COUNT); + for (int i = 0; i < OBJECTS_COUNT; ++i) { + struct object_t *obj = &g_vars.objects_tbl[i]; + obj->spr_num = 0xFFFF; + } + video_load_sprites(); + g_vars.tilemap.x = g_vars.tilemap.scroll_dx = 0; + g_vars.tilemap.y = g_vars.tilemap.scroll_dy = 0; g_vars.objects_tbl[1].x_pos = 0; g_vars.objects_tbl[1].y_pos = 169; g_vars.objects_tbl[1].data.p.hdir = 0; g_vars.objects_tbl[1].x_velocity = 0; - static const uint8_t data[] = { - 0, 0, 0, 0, 1, 0, 1, 0, 2, 0, 2, 0, 3, 0, 3, 0, - 4, 0, 4, 0, 5, 0, 5, 0, 0xE8, 0xFF - }; - g_vars.objects_tbl[1].data.p.anim = data; + g_vars.objects_tbl[1].data.p.anim = demo_anim_data; g_vars.objects_tbl[2].x_pos = 48; g_vars.objects_tbl[2].y_pos = 169; - g_vars.objects_tbl[2].x_velocity = 0; + g_vars.objects_tbl[2].data.m.x_velocity = 0; + g_vars.objects_tbl[2].data.m.y_velocity = 0; g_vars.objects_tbl[2].data.m.anim = &monster_anim_tbl[0x2EA]; - g_vars.player_flying_flag = 0; + g_vars.player_flying_flag = false; int counter = 0; do { ++counter; @@ -3761,6 +3771,9 @@ void do_demo_animation() { update_object_demo_animation(&g_vars.objects_tbl[2]); level_draw_objects(); level_sync(); + if (g_sys.input.quit) { + return; + } int dx = 5; g_vars.objects_tbl[1].x_pos += dx; if ((counter & 3) == 0) { @@ -3794,10 +3807,114 @@ void do_demo_animation() { } level_draw_objects(); level_sync(); + if (g_sys.input.quit) { + return; + } g_vars.objects_tbl[1].x_pos -= 7; } while (g_vars.objects_tbl[1].x_pos >= 0); } +static const int GAMEOVER_Y_OFFSET = 185; + +static void do_gameover_animation_helper() { + if ((g_vars.level_draw_counter & 3) == 0) { + int spr_num = (g_vars.objects_tbl[21].spr_num & 0x1FFF) + 1; + if (spr_num >= 110) { + spr_num = 104; + } + g_vars.objects_tbl[21].spr_num = spr_num; + } + for (int i = 0; i < 8; ++i) { + struct object_t *obj = &g_vars.objects_tbl[1 + i]; + int y_vel = obj->data.m.y_velocity + 1; + if (y_vel >= 8) { + y_vel = 1 - y_vel; + } + obj->data.m.y_velocity = y_vel; + obj->y_pos += y_vel; + } + for (int i = 0; i < 3; ++i) { + struct object_t *obj = &g_vars.objects_tbl[31 + i]; + obj[-20].spr_num = 0xFFFF; + const int rx = (((int8_t)cos_tbl[obj->x_friction]) * 65) >> 6; + obj->x_pos = rx + 150; + const int ry = (((int8_t)sin_tbl[obj->x_friction]) * 10) >> 6; + obj->y_pos = ry + 309 - GAMEOVER_Y_OFFSET; + obj->data.m.x_velocity = ry; + obj->x_friction += 2; + update_object_demo_animation(obj); + } + for (int i = 0; i < 2; ++i) { + struct object_t *si = &g_vars.objects_tbl[31 + i]; + struct object_t *di = si + 1; + if (di->y_pos >= si->x_pos) { + SWAP(*si, *di); + } + } + for (int i = 0; i < 2; ++i) { + struct object_t *di = &g_vars.objects_tbl[11 + i]; + struct object_t *si = &g_vars.objects_tbl[31 + i]; + if (si->y_pos >= 309 - GAMEOVER_Y_OFFSET) { + *di = *si; + si->spr_num = 0xFFFF; + } + } +} + +void do_gameover_animation() { + memset(&g_vars.objects_tbl[0], 0, sizeof(struct object_t) * OBJECTS_COUNT); + for (int i = 0; i < OBJECTS_COUNT; ++i) { + g_vars.objects_tbl[i].spr_num = 0xFFFF; + } + video_load_sprites(); + g_vars.tilemap.x = g_vars.tilemap.scroll_dx = 0; + g_vars.tilemap.y = g_vars.tilemap.scroll_dy = 0; + static const char *gameover = "GAMEOVER"; + int x_pos = 44; + for (int i = 0; i < 8; ++i) { + struct object_t *obj = &g_vars.objects_tbl[1 + i]; + obj->spr_num = 0xB0 + gameover[i]; + obj->x_pos = x_pos; + obj->y_pos = 224 - GAMEOVER_Y_OFFSET; + obj->data.m.y_velocity = random_get_number() & 7; + if (obj->data.m.y_velocity == 0) { + obj->data.m.y_velocity = 1; + } + x_pos += 24; + if (i == 3) { + x_pos += 48; + } + } + g_vars.objects_tbl[19].x_pos = 150; + g_vars.objects_tbl[19].y_pos = 309 - GAMEOVER_Y_OFFSET; + g_vars.objects_tbl[19].spr_num = 0x64; + g_vars.objects_tbl[20].x_pos = 151; + g_vars.objects_tbl[20].y_pos = 264 - GAMEOVER_Y_OFFSET; + g_vars.objects_tbl[20].spr_num = 0x1C4; + g_vars.objects_tbl[21].x_pos = 150; + g_vars.objects_tbl[21].y_pos = 289 - GAMEOVER_Y_OFFSET; + g_vars.objects_tbl[21].spr_num = 0x68; + g_vars.objects_tbl[22].x_pos = 150; + g_vars.objects_tbl[22].y_pos = 281 - GAMEOVER_Y_OFFSET; + g_vars.objects_tbl[22].spr_num = 0x62; + g_vars.objects_tbl[31].x_friction = 0; + g_vars.objects_tbl[31].data.m.anim = gameover_anim1_data; + g_vars.objects_tbl[32].x_friction = 85; + g_vars.objects_tbl[32].data.m.anim = gameover_anim3_data; + g_vars.objects_tbl[33].x_friction = 170; + g_vars.objects_tbl[33].data.m.anim = gameover_anim3_data; + int timer_counter = 0; + do { + do_gameover_animation_helper(); + level_draw_objects(); + level_update_panel(); + level_sync(); + if (g_sys.input.quit) { + return; + } + } while (timer_counter < 630 && !g_sys.input.space); +} + void do_level() { static const uint8_t music_tbl[] = { 9, 9, 0, 0, 0, 13, 4, 4, 10, 13, 16, 16, 16, 9, 14, 4 }; play_music(music_tbl[g_vars.level_num]); diff --git a/p2/screen.c b/p2/screen.c index cce81f7..e294f3b 100644 --- a/p2/screen.c +++ b/p2/screen.c @@ -115,6 +115,19 @@ void video_copy_img(const uint8_t *src) { decode_planar(src, g_res.background, 320, 320, 200, 0xFF); } +void video_copy_background() { + if (GAME_SCREEN_W * GAME_SCREEN_H == 64000) { + memcpy(g_res.vga, g_res.background, 320 * 200); + } else { + memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); + for (int y = 0; y < MIN(200, GAME_SCREEN_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 video_draw_panel(const uint8_t *src) { const int h = GAME_SCREEN_H - PANEL_H; const int x = (GAME_SCREEN_W - 320) / 2; diff --git a/p2/staticres.c b/p2/staticres.c index e42470e..a6e4689 100644 --- a/p2/staticres.c +++ b/p2/staticres.c @@ -138,6 +138,11 @@ const uint8_t menu_palette_data[] = { 0x30,0x08,0x38,0x30,0x08,0x38,0x30,0x08,0x34,0x20,0x14,0x34,0x20,0x14,0x34,0x20, 0x14,0x34,0x20,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; +const uint8_t gameover_palette_data[] = { + 0x00,0x00,0x00,0x38,0x28,0x20,0x28,0x18,0x10,0x20,0x10,0x08,0x04,0x00,0x1C,0x28, + 0x00,0x08,0x00,0x04,0x10,0x38,0x30,0x08,0x00,0x14,0x00,0x00,0x20,0x00,0x08,0x30, + 0x08,0x34,0x20,0x14,0x00,0x10,0x24,0x14,0x20,0x24,0x20,0x28,0x2C,0x38,0x38,0x38 +}; const uint8_t spr_offs_tbl[] = { 0x14,0x24,0x10,0x23,0x0C,0x24,0x10,0x24,0x10,0x25,0x10,0x25,0x0F,0x24,0x10,0x23, 0x0F,0x23,0x0F,0x23,0x0C,0x23,0x10,0x26,0x14,0x1F,0x18,0x1F,0x10,0x1F,0x10,0x24, @@ -543,3 +548,20 @@ const uint16_t snow_pattern1_data[] = { const uint16_t snow_pattern2_data[] = { 0x01B8,0x0001,0x0028,0x0370,0x0006,0x0064,0x0528,0x0001,0x00FF,0xFFFF }; +const uint8_t demo_anim_data[] = { + 0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00, + 0x04,0x00,0x04,0x00,0x05,0x00,0x05,0x00,0xE8,0xFF +}; +const uint8_t gameover_anim1_data[] = { + 0x01,0x00,0x01,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x02,0x00,0x02,0x00, + 0xF0,0xFF +}; +const uint8_t gameover_anim2_data[] = { + 0x26,0x00,0x26,0x00,0x26,0x00,0x26,0x00,0x25,0x00,0x25,0x00,0x25,0x00,0x25,0x00, + 0x27,0x00,0x27,0x00,0x27,0x00,0x27,0x00,0x25,0x00,0x25,0x00,0x25,0x00,0x25,0x00, + 0xE0,0xFF +}; +const uint8_t gameover_anim3_data[] = { + 0x81,0x00,0x81,0x00,0x81,0x00,0x82,0x00,0x82,0x00,0x82,0x00,0x83,0x00,0x83,0x00, + 0x83,0x00,0xEE,0xFF +}; diff --git a/sys.h b/sys.h index 8a1650c..a3544af 100644 --- a/sys.h +++ b/sys.h @@ -38,7 +38,7 @@ struct sys_t { struct input_t input; int (*init)(); void (*fini)(); - void (*set_screen_size)(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen, bool hybrid_color); + void (*set_screen_size)(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen); void (*set_screen_palette)(const uint8_t *colors, int offset, int count, int depth); void (*set_palette_amiga)(const uint16_t *colors, int offset); void (*set_copper_bars)(const uint16_t *data); diff --git a/sys_sdl2.c b/sys_sdl2.c index 4e1e162..16300d2 100644 --- a/sys_sdl2.c +++ b/sys_sdl2.c @@ -40,7 +40,6 @@ static uint32_t _screen_palette[256]; static uint32_t *_screen_buffer; static int _copper_color_key; static uint32_t _copper_palette[COPPER_BARS_H]; -static bool _hybrid_color; static SDL_GameController *_controller; static SDL_Joystick *_joystick; @@ -109,7 +108,7 @@ static void sdl2_fini() { SDL_Quit(); } -static void sdl2_set_screen_size(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen, bool hybrid_color) { +static void sdl2_set_screen_size(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen) { assert(_screen_w == 0 && _screen_h == 0); // abort if called more than once _screen_w = w; _screen_h = h; @@ -138,7 +137,6 @@ static void sdl2_set_screen_size(int w, int h, const char *caption, int scale, c _sprites_cliprect.y = 0; _sprites_cliprect.w = w; _sprites_cliprect.h = h; - _hybrid_color = hybrid_color; } static uint32_t convert_amiga_color(uint16_t color) { @@ -198,9 +196,6 @@ static void sdl2_set_screen_palette(const uint8_t *colors, int offset, int count g = (g << shift) | (g >> (depth - shift)); b = (b << shift) | (b >> (depth - shift)); } - if(_hybrid_color && i < 2){ - g = 0; - } _screen_palette[offset + i] = SDL_MapRGB(_fmt, r, g, b); palette_colors[i].r = r; palette_colors[i].g = g; @@ -351,7 +346,7 @@ static void sdl2_shake_screen(int dx, int dy) { _shake_dy = dy; } -static void handle_keyevent(int keysym, bool keydown, struct input_t *input) { +static void handle_keyevent(int keysym, bool keydown, struct input_t *input, bool *paused) { switch (keysym) { case SDLK_LEFT: if (keydown) { @@ -399,6 +394,11 @@ static void handle_keyevent(int keysym, bool keydown, struct input_t *input) { case SDLK_3: input->digit3 = keydown; break; + case SDLK_p: + if (!keydown) { + *paused = !*paused; + } + break; } } @@ -434,7 +434,7 @@ static void handle_controlleraxis(int axis, int value, struct input_t *input) { } } -static void handle_controllerbutton(int button, bool pressed, struct input_t *input) { +static void handle_controllerbutton(int button, bool pressed, struct input_t *input, bool *paused) { switch (button) { case SDL_CONTROLLER_BUTTON_A: case SDL_CONTROLLER_BUTTON_B: @@ -446,6 +446,9 @@ static void handle_controllerbutton(int button, bool pressed, struct input_t *in g_sys.input.quit = true; break; case SDL_CONTROLLER_BUTTON_START: + if (!pressed) { + *paused = !*paused; + } break; case SDL_CONTROLLER_BUTTON_DPAD_UP: if (pressed) { @@ -532,15 +535,14 @@ static int handle_event(const SDL_Event *ev, bool *paused) { case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_FOCUS_LOST: *paused = (ev->window.event == SDL_WINDOWEVENT_FOCUS_LOST); - SDL_PauseAudio(*paused); break; } break; case SDL_KEYUP: - handle_keyevent(ev->key.keysym.sym, 0, &g_sys.input); + handle_keyevent(ev->key.keysym.sym, 0, &g_sys.input, paused); break; case SDL_KEYDOWN: - handle_keyevent(ev->key.keysym.sym, 1, &g_sys.input); + handle_keyevent(ev->key.keysym.sym, 1, &g_sys.input, paused); break; case SDL_CONTROLLERDEVICEADDED: if (!_controller) { @@ -559,12 +561,12 @@ static int handle_event(const SDL_Event *ev, bool *paused) { break; case SDL_CONTROLLERBUTTONUP: if (_controller) { - handle_controllerbutton(ev->cbutton.button, 0, &g_sys.input); + handle_controllerbutton(ev->cbutton.button, 0, &g_sys.input, paused); } break; case SDL_CONTROLLERBUTTONDOWN: if (_controller) { - handle_controllerbutton(ev->cbutton.button, 1, &g_sys.input); + handle_controllerbutton(ev->cbutton.button, 1, &g_sys.input, paused); } break; case SDL_CONTROLLERAXISMOTION: @@ -603,10 +605,14 @@ static void sdl2_process_events() { while (1) { SDL_Event ev; while (SDL_PollEvent(&ev)) { + const bool prev = paused; handle_event(&ev, &paused); if (g_sys.input.quit) { break; } + if (prev != paused) { + SDL_PauseAudio(paused); + } } if (!paused) { break;