Import blues from 3ac3f56f

This commit is contained in:
Gregory Montoir 2022-03-13 06:26:29 +08:00
parent cc3f301495
commit 140c6cdb1e
12 changed files with 306 additions and 88 deletions

View File

@ -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;
};

View File

@ -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];

View File

@ -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) {

4
main.c
View File

@ -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();
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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]);

View File

@ -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;

View File

@ -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
};

2
sys.h
View File

@ -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);

View File

@ -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;