Import blues from 1d309d39

This commit is contained in:
Gregory Montoir 2018-08-12 20:27:20 +08:00
parent e46e90d22a
commit 79f3e35872
12 changed files with 225 additions and 226 deletions

View File

@ -8,7 +8,7 @@ This is a rewrite of the game [Blues Brothers](https://www.mobygames.com/game/bl
## Requirements ## Requirements
The game data files of the DOS version (retail or demo) are required. The game data files of the DOS or Amiga version are required.
``` ```
*.BIN, *.CK1, *.CK2, *.SQL, *.SQV, *.SQZ *.BIN, *.CK1, *.CK2, *.SQL, *.SQV, *.SQZ

30
game.c
View File

@ -24,12 +24,12 @@ void update_input() {
g_vars.inp_key_up = ((g_sys.input.direction & INPUT_DIRECTION_UP) != 0) || g_vars.inp_keyboard[0x48] || g_vars.inp_keyboard[0x7C]; g_vars.inp_key_up = ((g_sys.input.direction & INPUT_DIRECTION_UP) != 0) || g_vars.inp_keyboard[0x48] || g_vars.inp_keyboard[0x7C];
g_vars.inp_key_down = ((g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0) || g_vars.inp_keyboard[0x50] || g_vars.inp_keyboard[0x7B]; g_vars.inp_key_down = ((g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0) || g_vars.inp_keyboard[0x50] || g_vars.inp_keyboard[0x7B];
g_vars.inp_key_space = g_sys.input.space || g_vars.inp_keyboard[0x39] || g_vars.inp_keyboard[0x77]; g_vars.inp_key_space = g_sys.input.space || g_vars.inp_keyboard[0x39] || g_vars.inp_keyboard[0x77];
g_vars.inp_key_tab = g_vars.inp_keyboard[0xF] || g_vars.inp_keyboard[0x78]; // g_vars.inp_key_tab = g_vars.inp_keyboard[0xF] || g_vars.inp_keyboard[0x78];
} }
void do_title_screen() { void do_title_screen() {
const uint32_t timestamp = g_sys.get_timestamp() + 20 * 1000; const uint32_t timestamp = g_sys.get_timestamp() + 20 * 1000;
load_img(g_options.amiga_data ? "blues.lbm" : "pres.sqz", GAME_SCREEN_W); load_img(g_res.amiga_data ? "blues.lbm" : "pres.sqz", GAME_SCREEN_W);
fade_in_palette(); fade_in_palette();
do { do {
update_input(); update_input();
@ -50,11 +50,11 @@ void do_select_player() {
int frame2 = 1; int frame2 = 1;
const int color_rgb = 2; const int color_rgb = 2;
const int colors_count = 25; const int colors_count = 25;
load_img(g_options.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W); load_img(g_res.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W);
screen_load_graphics(); screen_load_graphics();
screen_clear_sprites(); screen_clear_sprites();
do { do {
screen_unk4(); screen_copy_img();
update_input(); update_input();
const uint32_t timestamp = g_sys.get_timestamp(); const uint32_t timestamp = g_sys.get_timestamp();
switch (state) { switch (state) {
@ -181,13 +181,11 @@ void do_select_player() {
} }
continue; continue;
} }
screen_clear_last_sprite();
screen_redraw_sprites(); screen_redraw_sprites();
screen_flip(); screen_flip();
screen_vsync(); screen_vsync();
const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp(); const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp();
g_sys.sleep(diff < 10 ? 10 : diff); g_sys.sleep(diff < 10 ? 10 : diff);
g_vars.screen_draw_offset ^= 0x2000;
screen_clear_sprites(); screen_clear_sprites();
if (g_sys.input.space || g_vars.play_demo_flag) { if (g_sys.input.space || g_vars.play_demo_flag) {
quit = 1; quit = 1;
@ -196,12 +194,8 @@ void do_select_player() {
} }
static void do_inter_screen_helper(int xpos, int ypos, int c) { static void do_inter_screen_helper(int xpos, int ypos, int c) {
if (c != 0) {
g_vars.screen_draw_offset ^= 0x2000;
}
for (int i = 0; i < 40; ++i) { for (int i = 0; i < 40; ++i) {
screen_add_sprite(xpos + 20 - 1 - i, ypos - 20 + 1 + i, 125); screen_add_sprite(xpos + 20 - 1 - i, ypos - 20 + 1 + i, 125);
screen_clear_last_sprite();
screen_redraw_sprites(); screen_redraw_sprites();
if (c != 0) { if (c != 0) {
screen_vsync(); screen_vsync();
@ -210,22 +204,18 @@ static void do_inter_screen_helper(int xpos, int ypos, int c) {
} }
for (int i = 0; i < 40; ++i) { for (int i = 0; i < 40; ++i) {
screen_add_sprite(xpos - 20 + 1 + i, ypos - 20 + 1 + i, 125); screen_add_sprite(xpos - 20 + 1 + i, ypos - 20 + 1 + i, 125);
screen_clear_last_sprite();
screen_redraw_sprites(); screen_redraw_sprites();
if (c != 0) { if (c != 0) {
screen_vsync(); screen_vsync();
} }
screen_clear_sprites(); screen_clear_sprites();
} }
if (c != 0) {
g_vars.screen_draw_offset ^= 0x2000;
}
} }
static void do_inter_screen() { static void do_inter_screen() {
static const uint8_t xpos[] = { 0xFA, 0x50, 0xF0, 0xC8, 0x50, 0x50 }; static const uint8_t xpos[] = { 0xFA, 0x50, 0xF0, 0xC8, 0x50, 0x50 };
static const uint8_t ypos[] = { 0xAA, 0x37, 0x28, 0x5F, 0xA5, 0xAA }; static const uint8_t ypos[] = { 0xAA, 0x37, 0x28, 0x5F, 0xA5, 0xAA };
load_img(g_options.amiga_data ? "inter.lbm" : "inter.sqz", GAME_SCREEN_W); load_img(g_res.amiga_data ? "inter.lbm" : "inter.sqz", GAME_SCREEN_W);
g_vars.screen_draw_h = GAME_SCREEN_H - 1; g_vars.screen_draw_h = GAME_SCREEN_H - 1;
screen_clear_sprites(); screen_clear_sprites();
if (g_vars.level > 1) { if (g_vars.level > 1) {
@ -240,16 +230,13 @@ static void do_inter_screen() {
if (g_vars.level > 0 && g_vars.level < MAX_LEVELS - 1) { if (g_vars.level > 0 && g_vars.level < MAX_LEVELS - 1) {
do_inter_screen_helper(xpos[g_vars.level - 1], ypos[g_vars.level - 1], 1); do_inter_screen_helper(xpos[g_vars.level - 1], ypos[g_vars.level - 1], 1);
} }
g_vars.screen_draw_offset = 0x2000; // screen_do_transition2();
screen_do_transition2();
screen_flip(); screen_flip();
if (g_vars.level < MAX_LEVELS - 1) { if (g_vars.level < MAX_LEVELS - 1) {
play_sound(SOUND_2); play_sound(SOUND_2);
screen_add_sprite(xpos[g_vars.level], ypos[g_vars.level], 126); screen_add_sprite(xpos[g_vars.level], ypos[g_vars.level], 126);
screen_clear_last_sprite();
screen_redraw_sprites(); screen_redraw_sprites();
} }
g_vars.screen_draw_offset = 0x2000;
screen_flip(); screen_flip();
const uint32_t timestamp = g_sys.get_timestamp() + 4 * 1000; const uint32_t timestamp = g_sys.get_timestamp() + 4 * 1000;
do { do {
@ -263,17 +250,16 @@ static void do_inter_screen() {
void game_main() { void game_main() {
play_music(0); play_music(0);
g_vars.screen_draw_offset = 0;
screen_init(); screen_init();
screen_flip(); screen_flip();
g_vars.start_level = 0; g_vars.start_level = 0;
if (g_options.amiga_data) { if (g_res.amiga_data) {
load_spr("sprite", g_res.spr_sqv, 0); load_spr("sprite", g_res.spr_sqv, 0);
load_spr("objet", g_res.spr_sqv + SPRITE_SIZE, 101); load_spr("objet", g_res.spr_sqv + SPRITE_SIZE, 101);
} else { } else {
load_sqv("sprite.sqv", g_res.spr_sqv, 0); load_sqv("sprite.sqv", g_res.spr_sqv, 0);
} }
if (g_options.amiga_status_bar) { if (g_options.amiga_status_bar || g_res.amiga_data) {
uint16_t palette[16]; uint16_t palette[16];
for (int i = 0; i < 16; ++i) { for (int i = 0; i < 16; ++i) {
assert(_colors_180_data[i * 2] == 0x180 + i * 2); assert(_colors_180_data[i * 2] == 0x180 + i * 2);

32
game.h
View File

@ -10,6 +10,7 @@
#define TILEMAP_OFFSET_Y 14 #define TILEMAP_OFFSET_Y 14
#define TILEMAP_SCREEN_W GAME_SCREEN_W #define TILEMAP_SCREEN_W GAME_SCREEN_W
#define TILEMAP_SCREEN_H (GAME_SCREEN_H - 40) #define TILEMAP_SCREEN_H (GAME_SCREEN_H - 40)
#define TILEMAP_SCROLL_W 64
#define PLAYER_JAKE 0 #define PLAYER_JAKE 0
#define PLAYER_ELWOOD 1 #define PLAYER_ELWOOD 1
@ -46,8 +47,8 @@ struct options_t {
int screen_h; int screen_h;
bool amiga_copper_bars; bool amiga_copper_bars;
bool amiga_colors; bool amiga_colors;
bool amiga_data;
bool amiga_status_bar; bool amiga_status_bar;
bool dos_scrolling;
}; };
extern struct options_t g_options; extern struct options_t g_options;
@ -150,12 +151,11 @@ struct vars_t {
int16_t level_xpos[MAX_OBJECTS]; int16_t level_xpos[MAX_OBJECTS];
int16_t level_ypos[MAX_OBJECTS]; int16_t level_ypos[MAX_OBJECTS];
int screen_tilemap_w, screen_tilemap_h; int screen_tilemap_w, screen_tilemap_h;
int screen_tilemap_w16, screen_tilemap_h16;
int screen_tilemap_xorigin, screen_tilemap_yorigin; int screen_tilemap_xorigin, screen_tilemap_yorigin;
int screen_tilemap_xoffset, screen_tilemap_yoffset; int screen_tilemap_xoffset, screen_tilemap_yoffset;
int screen_tilemap_size_w, screen_tilemap_size_h; int screen_tilemap_size_w, screen_tilemap_size_h;
int screen_scrolling_dirmask, screen_unk1; int screen_scrolling_dirmask;
int screen_draw_h, screen_draw_offset; int screen_draw_h;
int screen_tile_lut[256]; int screen_tile_lut[256];
bool level_completed_flag; bool level_completed_flag;
bool play_level_flag; bool play_level_flag;
@ -167,17 +167,17 @@ struct vars_t {
bool play_demo_flag; bool play_demo_flag;
bool quit_level_flag; bool quit_level_flag;
bool two_players_flag; bool two_players_flag;
bool switch_player_scrolling_flag;
int music_num; int music_num;
uint8_t inp_keyboard[256]; uint8_t inp_keyboard[256];
int inp_key_space; bool inp_key_space;
int inp_key_tab; bool inp_key_up;
int inp_key_up; bool inp_key_down;
int inp_key_down; bool inp_key_right;
int inp_key_right; bool inp_key_left;
int inp_key_left; bool inp_key_up_prev;
int inp_key_up_prev; bool inp_key_down_prev;
int inp_key_down_prev; bool inp_key_action;
int inp_key_action;
struct door_t doors[MAX_DOORS]; struct door_t doors[MAX_DOORS];
struct object_t objects[MAX_OBJECTS]; struct object_t objects[MAX_OBJECTS];
int vinyls_count; int vinyls_count;
@ -240,7 +240,6 @@ extern void level_call_object_func(struct object_t *);
extern void screen_init(); extern void screen_init();
extern void screen_clear_sprites(); extern void screen_clear_sprites();
extern void screen_add_sprite(int x, int y, int frame); extern void screen_add_sprite(int x, int y, int frame);
extern void screen_clear_last_sprite();
extern void screen_redraw_sprites(); extern void screen_redraw_sprites();
extern void fade_in_palette(); extern void fade_in_palette();
extern void fade_out_palette(); extern void fade_out_palette();
@ -248,13 +247,12 @@ extern void screen_adjust_palette_color(int color, int b, int c);
extern void screen_vsync(); extern void screen_vsync();
extern void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y); extern void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y);
extern void screen_flip(); extern void screen_flip();
extern void screen_unk4(); extern void screen_copy_img();
extern void screen_unk5(); extern void screen_unk5();
extern void screen_unk6();
extern void screen_do_transition1(int a); extern void screen_do_transition1(int a);
extern void screen_do_transition2(); extern void screen_do_transition2();
extern void screen_clear(int a); extern void screen_clear(int a);
extern void screen_draw_tile(int tile, int dst, int type); extern void screen_draw_tile(int tile, int type, int x, int y);
extern void screen_draw_number(int num, int x, int y, int color); extern void screen_draw_number(int num, int x, int y, int color);
extern void screen_add_game_sprite1(int x, int y, int frame); extern void screen_add_game_sprite1(int x, int y, int frame);
extern void screen_add_game_sprite2(int x, int y, int frame); extern void screen_add_game_sprite2(int x, int y, int frame);

View File

@ -9,15 +9,6 @@
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#ifndef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#endif
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
#ifndef ABS
#define ABS(a) (((a)<0)?(-(a)):(a))
#endif
#ifndef ARRAYSIZE #ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif #endif

209
level.c
View File

@ -60,7 +60,7 @@ static const struct {
void load_level_data(int num) { void load_level_data(int num) {
print_debug(DBG_GAME, "load_level_data num %d", num); print_debug(DBG_GAME, "load_level_data num %d", num);
if (g_options.amiga_data) { if (g_res.amiga_data) {
load_blk(_levels_amiga[num].blk); load_blk(_levels_amiga[num].blk);
read_file(_levels_amiga[num].tbl, g_res.sql, 0); read_file(_levels_amiga[num].tbl, g_res.sql, 0);
load_bin(_levels_amiga[num].bin); load_bin(_levels_amiga[num].bin);
@ -68,7 +68,7 @@ void load_level_data(int num) {
// .avt // .avt
load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT); load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT);
} else { } else {
if (num == 0 && (g_res.flags & RESOURCE_FLAGS_DEMO)) { // DOS demo if (num == 0 && g_res.dos_demo) {
load_ck("demomag.ck1", 0x6000); load_ck("demomag.ck1", 0x6000);
load_ck("demomag.ck2", 0x8000); load_ck("demomag.ck2", 0x8000);
load_sql("demomag.sql"); load_sql("demomag.sql");
@ -261,24 +261,21 @@ static void init_level() {
} }
static void do_level_redraw_tilemap(int xpos, int ypos) { static void do_level_redraw_tilemap(int xpos, int ypos) {
const int w = TILEMAP_SCREEN_W / 16; const int w = (TILEMAP_SCREEN_W / 16) + ((!g_options.dos_scrolling && (xpos & 15) != 0) ? 1 : 0);
const int h = TILEMAP_SCREEN_H / 16; const int h = (TILEMAP_SCREEN_H / 16) + ((!g_options.dos_scrolling && (ypos & 15) != 0) ? 1 : 0);
int y = ypos >> 4; const int y = ypos >> 4;
int x = xpos >> 4; const int x = xpos >> 4;
for (int j = 0; j < h * 640; j += 640) { for (int j = 0; j < h; ++j) {
const uint8_t *ptr = lookup_sql(x, y); const uint8_t *ptr = lookup_sql(x, y + j);
for (int i = 0; i < w * 2; i += 2) { for (int i = 0; i < w; ++i) {
const uint8_t num = *ptr++; const uint8_t num = *ptr++;
if (num >= 128) { if (num >= 128) {
screen_draw_tile(g_vars.screen_tile_lut[num - 128], j + i, 4); screen_draw_tile(g_vars.screen_tile_lut[num - 128], 4, i, j);
} else { } else {
screen_draw_tile(g_vars.screen_tile_lut[num], j + i, 3); screen_draw_tile(g_vars.screen_tile_lut[num], 3, i, j);
} }
} }
++y;
} }
g_vars.screen_tilemap_xoffset = 0;
g_vars.screen_tilemap_yoffset = 0;
g_vars.screen_tilemap_size_w = w; g_vars.screen_tilemap_size_w = w;
g_vars.screen_tilemap_size_h = h; g_vars.screen_tilemap_size_h = h;
} }
@ -292,11 +289,13 @@ static void do_level_update_tiles_anim() {
++p[0]; ++p[0];
} }
} }
int y = g_vars.screen_tilemap_yorigin >> 4; const int w = (TILEMAP_SCREEN_W / 16) + ((!g_options.dos_scrolling && (g_vars.screen_tilemap_xorigin & 15) != 0) ? 1 : 0);
int x = g_vars.screen_tilemap_xorigin >> 4; const int h = (TILEMAP_SCREEN_H / 16) + ((!g_options.dos_scrolling && (g_vars.screen_tilemap_yorigin & 15) != 0) ? 1 : 0);
for (int j = 0; j < (TILEMAP_SCREEN_H / 16) * 640; j += 640) { const int y = g_vars.screen_tilemap_yorigin >> 4;
uint8_t *ptr = lookup_sql(x, y); const int x = g_vars.screen_tilemap_xorigin >> 4;
for (int i = 0; i < (TILEMAP_SCREEN_W / 16) * 2; i += 2, ++ptr) { for (int j = 0; j < h; ++j) {
uint8_t *ptr = lookup_sql(x, y + j);
for (int i = 0; i < w; ++i, ++ptr) {
uint8_t num = *ptr; uint8_t num = *ptr;
struct trigger_t *t = &g_res.triggers[num]; struct trigger_t *t = &g_res.triggers[num];
const uint8_t *data = t->op_table2; const uint8_t *data = t->op_table2;
@ -314,12 +313,11 @@ static void do_level_update_tiles_anim() {
t->unk16 = num; t->unk16 = num;
} }
if (num >= 128) { if (num >= 128) {
screen_draw_tile(g_vars.screen_tile_lut[num - 128], j + i, 4); screen_draw_tile(g_vars.screen_tile_lut[num - 128], 4, i, j);
} else { } else {
screen_draw_tile(g_vars.screen_tile_lut[num], j + i, 3); screen_draw_tile(g_vars.screen_tile_lut[num], 3, i, j);
} }
} }
++y;
} }
} }
@ -327,27 +325,58 @@ static void do_level_update_scrolling2() {
if (g_vars.screen_scrolling_dirmask & 2) { if (g_vars.screen_scrolling_dirmask & 2) {
if (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W > g_vars.screen_tilemap_xorigin) { if (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W > g_vars.screen_tilemap_xorigin) {
g_vars.screen_tilemap_xorigin += 16; g_vars.screen_tilemap_xorigin += 16;
// do_level_update_scrolling_left();
} }
} }
if (g_vars.screen_scrolling_dirmask & 1) { if (g_vars.screen_scrolling_dirmask & 1) {
if (g_vars.screen_tilemap_xorigin > 0) { if (g_vars.screen_tilemap_xorigin > 0) {
g_vars.screen_tilemap_xorigin -= 16; g_vars.screen_tilemap_xorigin -= 16;
// do_level_update_scrolling_right();
} }
} }
if (g_vars.screen_scrolling_dirmask & 8) { if (g_vars.screen_scrolling_dirmask & 8) {
if (g_vars.screen_tilemap_yorigin > 0) { if (g_vars.screen_tilemap_yorigin > 0) {
g_vars.screen_tilemap_yorigin -= 16; g_vars.screen_tilemap_yorigin -= 16;
// do_level_update_scrolling_top();
} }
} }
if (g_vars.screen_scrolling_dirmask & 4) { if (g_vars.screen_scrolling_dirmask & 4) {
if (g_vars.screen_tilemap_h - TILEMAP_SCREEN_H > g_vars.screen_tilemap_yorigin) { if (g_vars.screen_tilemap_h - TILEMAP_SCREEN_H > g_vars.screen_tilemap_yorigin) {
g_vars.screen_tilemap_yorigin += 16; g_vars.screen_tilemap_yorigin += 16;
// do_level_update_scrolling_bottom();
} }
} }
if (!g_options.dos_scrolling) {
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;
if (g_vars.screen_tilemap_xorigin + TILEMAP_SCREEN_W > g_vars.screen_tilemap_w * 16) {
g_vars.screen_tilemap_xorigin = g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W;
}
} else if (obj->screen_xpos < x1) {
const int dx = obj->screen_xpos - x1;
g_vars.screen_tilemap_xorigin += dx;
if (g_vars.screen_tilemap_xorigin < 0) {
g_vars.screen_tilemap_xorigin = 0;
}
}
const int y1 = 64;
const int y2 = 144;
if (obj->screen_ypos > y2) {
const int dy = obj->screen_ypos - y2;
g_vars.screen_tilemap_yorigin += dy;
if (g_vars.screen_tilemap_yorigin + TILEMAP_SCREEN_H > g_vars.screen_tilemap_h) {
g_vars.screen_tilemap_yorigin = g_vars.screen_tilemap_h - TILEMAP_SCREEN_H;
}
} else if (obj->screen_ypos < y1) {
const int dy = obj->screen_ypos - y1;
g_vars.screen_tilemap_yorigin += dy;
if (g_vars.screen_tilemap_yorigin < 0) {
g_vars.screen_tilemap_yorigin = 0;
}
}
g_vars.screen_tilemap_xoffset = -(g_vars.screen_tilemap_xorigin & 15);
g_vars.screen_tilemap_yoffset = -(g_vars.screen_tilemap_yorigin & 15);
}
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin); do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
if ((g_vars.level_loop_counter & 3) == 0) { if ((g_vars.level_loop_counter & 3) == 0) {
do_level_update_tiles_anim(); do_level_update_tiles_anim();
@ -376,7 +405,7 @@ static void do_level_add_sprite1_case0(struct object_t *obj) {
} else if (triggers_get_tile_type(obj->xpos16, obj->ypos16) == 4) { } else if (triggers_get_tile_type(obj->xpos16, obj->ypos16) == 4) {
anim_data = obj->animframes_ptr[28 / 4]; anim_data = obj->animframes_ptr[28 / 4];
} else { } else {
if (ABS(obj->yvelocity) > 10 && obj->yvelocity > 0) { if (abs(obj->yvelocity) > 10 && obj->yvelocity > 0) {
anim_data = obj->animframes_ptr[112 / 4]; anim_data = obj->animframes_ptr[112 / 4];
} else { } else {
anim_data = obj->animframes_ptr[8 / 4]; anim_data = obj->animframes_ptr[8 / 4];
@ -447,7 +476,7 @@ static void do_level_add_sprite1_case1(struct object_t *obj) {
anim_data = obj->animframes_ptr[0]; anim_data = obj->animframes_ptr[0];
} }
if (obj->unk2D < 8) { if (obj->unk2D < 8) {
if (ABS(obj->xvelocity) > 8) { if (abs(obj->xvelocity) > 8) {
anim_data = obj->animframes_ptr[24 / 4]; anim_data = obj->animframes_ptr[24 / 4];
} }
} }
@ -794,32 +823,35 @@ void do_level_update_tile(int x, int y, int num) {
uint8_t *ptr = lookup_sql(x, y); uint8_t *ptr = lookup_sql(x, y);
*ptr = num; *ptr = num;
const int tile_xpos = g_vars.screen_tilemap_xorigin >> 4;
const int tile_ypos = g_vars.screen_tilemap_yorigin >> 4;
const int w = (TILEMAP_SCREEN_W / 16) * 2; const int w = (TILEMAP_SCREEN_W / 16) * 2;
int _si = x * 2 + g_vars.screen_tilemap_yoffset - (g_vars.screen_tilemap_xorigin >> 3); int _si = (x + tile_xpos) * 2 + g_vars.screen_tilemap_xoffset;
if (_si > w - 2) { if (_si > w - 2) {
_si -= w; _si -= w;
} }
const int h = (TILEMAP_SCREEN_H / 16) * 640; const int h = (TILEMAP_SCREEN_H / 16) * 640;
int _di = (y - (g_vars.screen_tilemap_yorigin >> 4)) * 640 + g_vars.screen_tilemap_xoffset; int _di = (y - tile_ypos) * 640 + g_vars.screen_tilemap_yoffset;
if (_di > h - 640) { if (_di > h - 640) {
_di -= h; _di -= h;
} }
if ((g_vars.screen_tilemap_xorigin >> 4) > x) { if (tile_xpos > x) {
return; return;
} }
if ((g_vars.screen_tilemap_xorigin >> 4) + (TILEMAP_SCREEN_W / 16) <= x) { if (tile_xpos + (TILEMAP_SCREEN_W / 16) <= x) {
return; return;
} }
if ((g_vars.screen_tilemap_yorigin >> 4) > y) { if (tile_ypos > y) {
return; return;
} }
if ((g_vars.screen_tilemap_yorigin >> 4) + (TILEMAP_SCREEN_H / 16) <= y) { if (tile_ypos + (TILEMAP_SCREEN_H / 16) <= y) {
return; return;
} }
if (num >= 128) { if (num >= 128) {
screen_draw_tile(g_vars.screen_tile_lut[num - 128], _di + _si, 4); screen_draw_tile(g_vars.screen_tile_lut[num - 128], 4, _si / 2, _di / 640);
} else { } else {
screen_draw_tile(g_vars.screen_tile_lut[num], _di + _si, 3); screen_draw_tile(g_vars.screen_tile_lut[num], 3, _si / 2, _di / 640);
} }
} }
@ -983,28 +1015,16 @@ void do_level_update_panel_lifes(struct object_t *obj) {
static const uint16_t data[] = { 216, 232, 248, 264, 280, 296 }; static const uint16_t data[] = { 216, 232, 248, 264, 280, 296 };
for (int i = 0; i < obj->data51; ++i) { for (int i = 0; i < obj->data51; ++i) {
screen_draw_frame(g_res.spr_frames[120 + i], 12, 16, data[i], 161); screen_draw_frame(g_res.spr_frames[120 + i], 12, 16, data[i], 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[120 + i], 12, 16, data[i], 161);
g_vars.screen_draw_offset ^= 0x2000;
} }
for (int i = obj->data51; i < 5; ++i) { for (int i = obj->data51; i < 5; ++i) {
screen_draw_frame(g_res.spr_frames[119 + i], 12, 16, data[i], 161); screen_draw_frame(g_res.spr_frames[119 + i], 12, 16, data[i], 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[119 + i], 12, 16, data[i], 161);
g_vars.screen_draw_offset ^= 0x2000;
} }
} else { } else {
static const uint8_t data[] = { 18, 21, 20, 19, 19, 19 }; static const uint8_t data[] = { 18, 21, 20, 19, 19, 19 };
if (obj->type == PLAYER_JAKE) { if (obj->type == PLAYER_JAKE) {
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 80, 161); screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 80, 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 80, 161);
g_vars.screen_draw_offset ^= 0x2000;
} else { } else {
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 248, 161); screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 248, 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 248, 161);
g_vars.screen_draw_offset ^= 0x2000;
} }
} }
if (obj->data51 == 0) { // health if (obj->data51 == 0) { // health
@ -1017,33 +1037,21 @@ void do_level_update_panel_lifes(struct object_t *obj) {
obj->data51 = 3; obj->data51 = 3;
do_level_update_panel_lifes(obj); do_level_update_panel_lifes(obj);
if (obj->type == PLAYER_JAKE) { if (obj->type == PLAYER_JAKE) {
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 48, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 48, 163, 2); screen_draw_number(obj->lifes_count - 1, 48, 163, 2);
} else { } else {
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 216, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 216, 163, 2); screen_draw_number(obj->lifes_count - 1, 216, 163, 2);
} }
} else if (obj->type == PLAYER_JAKE) { } else if (obj->type == PLAYER_JAKE) {
g_vars.player2_scrolling_flag = 1; g_vars.player2_scrolling_flag = 1;
g_vars.screen_unk1 = 1; g_vars.switch_player_scrolling_flag = 1;
obj39->special_anim = 16; obj39->special_anim = 16;
g_vars.player2_dead_flag = 1; g_vars.player2_dead_flag = 1;
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[116], 12, 16, 8, 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[116], 12, 16, 8, 161); screen_draw_frame(g_res.spr_frames[116], 12, 16, 8, 161);
} else { // PLAYER_ELWOOD } else { // PLAYER_ELWOOD
g_vars.player2_scrolling_flag = 0; g_vars.player2_scrolling_flag = 0;
g_vars.screen_unk1 = 1; g_vars.switch_player_scrolling_flag = 1;
obj40->special_anim = 16; obj40->special_anim = 16;
g_vars.player1_dead_flag = 1; g_vars.player1_dead_flag = 1;
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[118], 12, 16, 176, 161);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[118], 12, 16, 176, 161); screen_draw_frame(g_res.spr_frames[118], 12, 16, 176, 161);
} }
if (g_vars.player2_dead_flag && g_vars.player1_dead_flag) { if (g_vars.player2_dead_flag && g_vars.player1_dead_flag) {
@ -1068,17 +1076,11 @@ static void do_level_update_panel_vinyls(struct object_t *obj) {
} }
if (!g_vars.two_players_flag) { if (!g_vars.two_players_flag) {
if (obj->vinyls_count != g_vars.vinyls_count) { if (obj->vinyls_count != g_vars.vinyls_count) {
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 192, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 192, 163, 2); screen_draw_number(obj->vinyls_count, 192, 163, 2);
} }
g_vars.vinyls_count = obj->vinyls_count; g_vars.vinyls_count = obj->vinyls_count;
} else { } else {
if (obj->vinyls_count != g_vars.vinyls_count) { if (obj->vinyls_count != g_vars.vinyls_count) {
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 112, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 112, 163, 2); screen_draw_number(obj->vinyls_count, 112, 163, 2);
} }
g_vars.vinyls_count = obj->vinyls_count; g_vars.vinyls_count = obj->vinyls_count;
@ -1100,9 +1102,6 @@ static void do_level_update_panel_2nd_player() {
do_level_update_panel_lifes(obj); do_level_update_panel_lifes(obj);
} }
if (obj->vinyls_count != g_vars.vinyls_count) { if (obj->vinyls_count != g_vars.vinyls_count) {
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 280, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->vinyls_count, 280, 163, 2); screen_draw_number(obj->vinyls_count, 280, 163, 2);
g_vars.vinyls_count = obj->vinyls_count; g_vars.vinyls_count = obj->vinyls_count;
} }
@ -1196,7 +1195,6 @@ void do_level_enter_door(struct object_t *obj) {
do_level_update_panel_2nd_player(); do_level_update_panel_2nd_player();
} }
screen_flip(); screen_flip();
g_vars.screen_draw_offset ^= 0x2000;
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin); do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
do_level_update_scrolling2(); do_level_update_scrolling2();
draw_level_panel(); draw_level_panel();
@ -1206,7 +1204,6 @@ void do_level_enter_door(struct object_t *obj) {
} }
screen_do_transition1(1); screen_do_transition1(1);
screen_flip(); screen_flip();
g_vars.screen_draw_offset ^= 0x2000;
obj->unk3D = 0; obj->unk3D = 0;
obj->sprite_type = 0; obj->sprite_type = 0;
obj->yacc = 2; obj->yacc = 2;
@ -1334,7 +1331,7 @@ static void do_level_update_scrolling(struct object_t *obj) {
g_vars.screen_scrolling_dirmask = 0; g_vars.screen_scrolling_dirmask = 0;
return; return;
} }
if (g_vars.screen_unk1) { if (g_vars.switch_player_scrolling_flag) {
if (obj->screen_xpos > (TILEMAP_SCREEN_W - 144)) { if (obj->screen_xpos > (TILEMAP_SCREEN_W - 144)) {
g_vars.screen_scrolling_dirmask |= 2; g_vars.screen_scrolling_dirmask |= 2;
} }
@ -1343,26 +1340,26 @@ static void do_level_update_scrolling(struct object_t *obj) {
} }
if ((g_vars.screen_scrolling_dirmask & 2) != 0 && obj->screen_xpos < TILEMAP_SCREEN_W / 2) { if ((g_vars.screen_scrolling_dirmask & 2) != 0 && obj->screen_xpos < TILEMAP_SCREEN_W / 2) {
g_vars.screen_scrolling_dirmask &= ~2; g_vars.screen_scrolling_dirmask &= ~2;
g_vars.screen_unk1 = 0; g_vars.switch_player_scrolling_flag = 0;
g_vars.inp_keyboard[0xC1] = 0; g_vars.inp_keyboard[0xC1] = 0;
} }
if ((g_vars.screen_scrolling_dirmask & 1) != 0 && obj->screen_xpos > TILEMAP_SCREEN_W / 2) { if ((g_vars.screen_scrolling_dirmask & 1) != 0 && obj->screen_xpos > TILEMAP_SCREEN_W / 2) {
g_vars.screen_scrolling_dirmask &= ~1; g_vars.screen_scrolling_dirmask &= ~1;
g_vars.screen_unk1 = 0; g_vars.switch_player_scrolling_flag = 0;
g_vars.inp_keyboard[0xC1] = 0; g_vars.inp_keyboard[0xC1] = 0;
} }
} else { } else {
int _si = (obj->xvelocity >> 3) + obj->unk1C; int _si = (obj->xvelocity >> 3) + obj->unk1C;
if (obj->screen_xpos > (TILEMAP_SCREEN_W - 64) && (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W) > g_vars.screen_tilemap_xorigin) { if (obj->screen_xpos > (TILEMAP_SCREEN_W - TILEMAP_SCROLL_W) && (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W) > g_vars.screen_tilemap_xorigin) {
g_vars.screen_scrolling_dirmask |= 2; g_vars.screen_scrolling_dirmask |= 2;
} }
if (obj->screen_xpos < 64 && g_vars.screen_tilemap_xorigin > 0) { if (obj->screen_xpos < TILEMAP_SCROLL_W && g_vars.screen_tilemap_xorigin > 0) {
g_vars.screen_scrolling_dirmask |= 1; g_vars.screen_scrolling_dirmask |= 1;
} }
if ((g_vars.screen_scrolling_dirmask & 2) != 0 && (obj->screen_xpos < 48 || _si <= 0)) { if ((g_vars.screen_scrolling_dirmask & 2) != 0 && (obj->screen_xpos < (TILEMAP_SCROLL_W - 16) || _si <= 0)) {
g_vars.screen_scrolling_dirmask &= ~2; g_vars.screen_scrolling_dirmask &= ~2;
} }
if ((g_vars.screen_scrolling_dirmask & 1) != 0 && (obj->screen_xpos > (TILEMAP_SCREEN_W - 48) || _si >= 0)) { if ((g_vars.screen_scrolling_dirmask & 1) != 0 && (obj->screen_xpos > (TILEMAP_SCREEN_W - (TILEMAP_SCROLL_W - 16)) || _si >= 0)) {
g_vars.screen_scrolling_dirmask &= ~1; g_vars.screen_scrolling_dirmask &= ~1;
} }
} }
@ -1392,7 +1389,7 @@ static void do_level_update_object_bounds(struct object_t *obj) {
tmp_dx = GAME_SCREEN_W; tmp_dx = GAME_SCREEN_W;
tmp_dy = GAME_SCREEN_H; tmp_dy = GAME_SCREEN_H;
} }
if (ABS(_si) >= ABS(tmp_dx) && ABS(_di) >= ABS(tmp_dy)) { if (abs(_si) >= abs(tmp_dx) && abs(_di) >= abs(tmp_dy)) {
obj->player_xdist = tmp_dx; obj->player_xdist = tmp_dx;
obj->player_ydist = tmp_dy; obj->player_ydist = tmp_dy;
// obj->unk41 = 1; // obj->unk41 = 1;
@ -1917,13 +1914,13 @@ static void do_level_update_objects() {
obj->direction_ud = 0; obj->direction_ud = 0;
if (obj->type < 2) { if (obj->type < 2) {
if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player
if (!g_vars.screen_unk1 && g_vars.two_players_flag) { 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].unk53 == 0) {
g_vars.player2_scrolling_flag = 1; g_vars.player2_scrolling_flag = 1;
g_vars.screen_unk1 = 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].unk53 == 0) {
g_vars.player2_scrolling_flag = 1; g_vars.player2_scrolling_flag = 1;
g_vars.screen_unk1 = 1; g_vars.switch_player_scrolling_flag = 1;
} }
} }
g_vars.inp_keyboard[0xC1] = 0; g_vars.inp_keyboard[0xC1] = 0;
@ -2026,15 +2023,9 @@ static void do_level_update_objects() {
if (g_vars.triggers_counter != 0) { if (g_vars.triggers_counter != 0) {
if (g_vars.triggers_counter < 10) { if (g_vars.triggers_counter < 10) {
screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, g_vars.level * 32 + 80, -12); screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, g_vars.level * 32 + 80, -12);
g_vars.screen_draw_offset = 0x2000;
screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, g_vars.level * 32 + 80, -12);
g_vars.screen_draw_offset ^= 0x2000;
++g_vars.triggers_counter; ++g_vars.triggers_counter;
} else { } else {
screen_draw_frame(g_res.spr_frames[145], 12, 16, g_vars.level * 32 + 80, -12); screen_draw_frame(g_res.spr_frames[145], 12, 16, g_vars.level * 32 + 80, -12);
g_vars.screen_draw_offset = 0x2000;
screen_draw_frame(g_res.spr_frames[145], 12, 16, g_vars.level * 32 + 80, -12);
g_vars.screen_draw_offset ^= 0x2000;
++g_vars.triggers_counter; ++g_vars.triggers_counter;
if (g_vars.triggers_counter > 20) { if (g_vars.triggers_counter > 20) {
g_vars.triggers_counter = 1; g_vars.triggers_counter = 1;
@ -2070,18 +2061,15 @@ static void do_level_update_objects() {
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0; g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level = 0; g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level = 0; g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level = 0;
g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
screen_unk5(); screen_unk5();
g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40;
g_vars.quit_level_flag = 1; g_vars.quit_level_flag = 1;
} }
} else if (g_vars.game_over_flag) { } else if (g_vars.game_over_flag) {
g_vars.screen_scrolling_dirmask = 0; g_vars.screen_scrolling_dirmask = 0;
if ((!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) || (g_vars.player2_dead_flag && g_vars.player1_dead_flag)) { if ((!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) || (g_vars.player2_dead_flag && g_vars.player1_dead_flag)) {
screen_draw_frame(g_res.spr_frames[127], 34, 160, 80, 63); screen_draw_frame(g_res.spr_frames[127], 34, 160, 80, 63);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[127], 34, 160, 80, 63);
g_vars.screen_draw_offset ^= 0x2000;
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0; g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0; g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0; g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
@ -2106,9 +2094,9 @@ static void do_level_update_objects() {
if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) { if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) {
g_vars.play_level_flag = 0; g_vars.play_level_flag = 0;
} }
g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
screen_unk5(); screen_unk5();
g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40;
g_vars.quit_level_flag = 1; g_vars.quit_level_flag = 1;
} }
} }
@ -2128,8 +2116,8 @@ static void draw_foreground_tiles() {
} }
const int avt_num = g_res.triggers[num].foreground_tile_num; const int avt_num = g_res.triggers[num].foreground_tile_num;
if (avt_num != 255) { if (avt_num != 255) {
const int tile_y = j * 16 + TILEMAP_OFFSET_Y; const int tile_y = g_vars.screen_tilemap_yoffset + j * 16 + TILEMAP_OFFSET_Y;
const int tile_x = i * 16; const int tile_x = g_vars.screen_tilemap_xoffset + i * 16;
render_add_sprite(RENDER_SPR_FG, avt_num, tile_x, tile_y, 0); render_add_sprite(RENDER_SPR_FG, avt_num, tile_x, tile_y, 0);
} }
} }
@ -2144,12 +2132,10 @@ void do_level() {
} }
g_vars.screen_tilemap_w = level_dim[g_vars.level * 2]; g_vars.screen_tilemap_w = level_dim[g_vars.level * 2];
g_vars.screen_tilemap_h = level_dim[g_vars.level * 2 + 1]; g_vars.screen_tilemap_h = level_dim[g_vars.level * 2 + 1];
g_vars.screen_tilemap_w16 = g_vars.screen_tilemap_w;
g_vars.screen_tilemap_h16 = g_vars.screen_tilemap_h >> 4;
for (int i = 0; i < MAX_TRIGGERS; ++i) { for (int i = 0; i < MAX_TRIGGERS; ++i) {
g_res.triggers[i].unk16 = i; g_res.triggers[i].unk16 = i;
} }
g_vars.screen_unk1 = 0; g_vars.switch_player_scrolling_flag = 0;
init_level(); init_level();
screen_clear(0); screen_clear(0);
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin); do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
@ -2160,7 +2146,7 @@ void do_level() {
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0); g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
} }
g_vars.inp_keyboard[0xB9] = 0; // SPACE g_vars.inp_keyboard[0xB9] = 0; // SPACE
g_vars.screen_draw_offset = TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset = TILEMAP_OFFSET_Y * 40;
g_vars.update_objects_counter = 0; g_vars.update_objects_counter = 0;
g_vars.game_over_flag = 0; g_vars.game_over_flag = 0;
g_vars.level_completed_flag = 0; g_vars.level_completed_flag = 0;
@ -2169,6 +2155,7 @@ void do_level() {
g_vars.screen_draw_h = TILEMAP_SCREEN_H; g_vars.screen_draw_h = TILEMAP_SCREEN_H;
g_vars.found_music_instrument_flag = 0; g_vars.found_music_instrument_flag = 0;
render_set_sprites_clipping_rect(0, TILEMAP_OFFSET_Y, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H); render_set_sprites_clipping_rect(0, TILEMAP_OFFSET_Y, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H);
bool screen_transition_flag = true;
do { do {
const uint32_t timestamp = g_sys.get_timestamp(); const uint32_t timestamp = g_sys.get_timestamp();
update_input(); update_input();
@ -2192,24 +2179,32 @@ void do_level() {
// demo // demo
do_level_update_scrolling2(); do_level_update_scrolling2();
do_level_update_objects(); do_level_update_objects();
screen_clear_last_sprite();
screen_redraw_sprites(); screen_redraw_sprites();
if (!g_options.amiga_data) { if (!g_res.amiga_data) {
draw_foreground_tiles(); draw_foreground_tiles();
} }
++g_vars.level_loop_counter; ++g_vars.level_loop_counter;
draw_level_panel(); draw_level_panel();
screen_unk6();
if (screen_transition_flag) {
screen_transition_flag = false;
g_sys.update_screen(g_res.vga, 0);
screen_do_transition2();
} else {
g_sys.update_screen(g_res.vga, 1);
}
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp(); const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp();
g_sys.sleep(diff < 10 ? 10 : diff); g_sys.sleep(diff < 10 ? 10 : diff);
screen_clear_sprites(); screen_clear_sprites();
} while (!g_sys.input.quit && !g_vars.quit_level_flag); } while (!g_sys.input.quit && !g_vars.quit_level_flag);
g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; // g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
screen_unk5(); screen_unk5();
if (g_options.amiga_copper_bars) { if (g_options.amiga_copper_bars) {
g_sys.set_copper_bars(0); g_sys.set_copper_bars(0);
} }
render_set_sprites_clipping_rect(0, 0, GAME_SCREEN_W, GAME_SCREEN_H);
g_vars.inp_keyboard[0xBF] = 0; g_vars.inp_keyboard[0xBF] = 0;
} }

5
main.c
View File

@ -35,8 +35,8 @@ int main(int argc, char *argv[]) {
g_options.screen_h = 200; g_options.screen_h = 200;
g_options.amiga_copper_bars = true; g_options.amiga_copper_bars = true;
g_options.amiga_colors = true; g_options.amiga_colors = true;
// g_options.amiga_data = true;
// g_options.amiga_status_bar = true; // g_options.amiga_status_bar = true;
g_options.dos_scrolling = false;
const char *data_path = DEFAULT_DATA_PATH; const char *data_path = DEFAULT_DATA_PATH;
int scale_factor = DEFAULT_SCALE_FACTOR; int scale_factor = DEFAULT_SCALE_FACTOR;
const char *scale_filter = DEFAULT_SCALE_FILTER; const char *scale_filter = DEFAULT_SCALE_FILTER;
@ -91,10 +91,11 @@ int main(int argc, char *argv[]) {
scale_filter = strdup(optarg); scale_filter = strdup(optarg);
break; break;
case 9: case 9:
sscanf(optarg, "%dx%d", &g_options.screen_w, &g_options.screen_h); if (sscanf(optarg, "%dx%d", &g_options.screen_w, &g_options.screen_h) == 2) {
// align to tile 16x16 // align to tile 16x16
g_options.screen_w = (g_options.screen_w + 15) & ~15; g_options.screen_w = (g_options.screen_w + 15) & ~15;
g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40; g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40;
}
break; break;
default: default:
fprintf(stdout, USAGE, argv[0]); fprintf(stdout, USAGE, argv[0]);

View File

@ -48,7 +48,10 @@ void res_init(int vga_size) {
} }
} }
if (fio_exists("demomag.sql")) { if (fio_exists("demomag.sql")) {
g_res.flags = RESOURCE_FLAGS_DEMO; g_res.dos_demo = true;
}
if (fio_exists("mag.tbl")) {
g_res.amiga_data = true;
} }
} }

View File

@ -28,10 +28,7 @@ struct trigger_t {
#define SOUND_SIZE 29376 #define SOUND_SIZE 29376
#define SPRITES_COUNT 146 #define SPRITES_COUNT 146
#define RESOURCE_FLAGS_DEMO (1 << 0)
struct resource_data_t { struct resource_data_t {
uint32_t flags;
uint8_t *sql; uint8_t *sql;
uint8_t *spr_sqv; uint8_t *spr_sqv;
uint8_t *avt_sqv; uint8_t *avt_sqv;
@ -46,6 +43,8 @@ struct resource_data_t {
int vga_size; int vga_size;
uint8_t *tiles; uint8_t *tiles;
uint8_t *snd; uint8_t *snd;
bool dos_demo;
bool amiga_data;
}; };
extern struct resource_data_t g_res; extern struct resource_data_t g_res;

View File

@ -41,9 +41,6 @@ void screen_add_sprite(int x, int y, int frame) {
add_game_sprite(x, y, frame, 0); add_game_sprite(x, y, frame, 0);
} }
void screen_clear_last_sprite() {
}
void screen_redraw_sprites() { void screen_redraw_sprites() {
} }
@ -70,7 +67,7 @@ void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y) {
y += _offset_y; y += _offset_y;
} }
y += fh + 2; y += fh + 2;
if (g_options.amiga_status_bar) { if (g_options.amiga_status_bar || g_res.amiga_data) {
if (frame == g_res.spr_frames[123] || frame == g_res.spr_frames[124]) { // top or bottom status bar if (frame == g_res.spr_frames[123] || frame == g_res.spr_frames[124]) { // top or bottom status bar
for (int x = 0; x < GAME_SCREEN_W; x += 16) { for (int x = 0; x < GAME_SCREEN_W; x += 16) {
decode_amiga_gfx(g_res.vga + y * GAME_SCREEN_W + x, GAME_SCREEN_W, 16, 12, 4, frame, 16, 0x20, 0xFFFF); decode_amiga_gfx(g_res.vga + y * GAME_SCREEN_W + x, GAME_SCREEN_W, 16, 12, 4, frame, 16, 0x20, 0xFFFF);
@ -91,64 +88,64 @@ void screen_flip() {
g_sys.update_screen(g_res.vga, 1); g_sys.update_screen(g_res.vga, 1);
} }
void screen_unk4() { void screen_copy_img() {
memcpy(g_res.vga, g_res.tmp + 32000, GAME_SCREEN_W * GAME_SCREEN_H); memcpy(g_res.vga, g_res.tmp + 32000, GAME_SCREEN_W * GAME_SCREEN_H);
} }
void screen_unk5() { void screen_unk5() {
screen_clear(0);
screen_do_transition2();
screen_clear(0);
}
void screen_unk6() {
// g_vars.screen_draw_offset -= 12;
// screen_do_transition2(); // screen_do_transition2();
// g_vars.screen_draw_offset += 12; screen_clear(0);
g_sys.update_screen(g_res.vga, 1);
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
}
static void screen_unk13(int a) {
} }
void screen_do_transition1(int a) { void screen_do_transition1(int a) {
int i, count, increment; print_warning("screen_do_transition1 %d", a);
if (a != 0) { if (a) {
i = 11; g_sys.transition_screen(TRANSITION_CURTAIN, true);
count = 0;
increment = -1;
} else {
screen_clear(0);
i = 0;
count = 11;
increment = 1;
}
while (i != count) {
screen_unk13(i);
screen_unk13(19 - i);
screen_vsync();
i += increment;
} }
} }
void screen_do_transition2() { void screen_do_transition2() {
print_warning("screen_do_transition2"); print_warning("screen_do_transition2");
g_sys.transition_screen(TRANSITION_SQUARE, true);
} }
void screen_clear(int a) { void screen_clear(int a) {
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
} }
void screen_draw_tile(int tile, int dst, int type) { void screen_draw_tile(int tile, int type, int x, int y) {
const int y = (dst / 640) * 16 + TILEMAP_OFFSET_Y;
const int x = (dst % 640) / 2 * 16;
const uint8_t *src = g_res.tiles + tile * 16; const uint8_t *src = g_res.tiles + tile * 16;
if (type == 4) { if (type == 4) {
src += 320; src += 320;
} }
for (int i = 0; i < 16; ++i) { x = g_vars.screen_tilemap_xoffset + x * 16;
memcpy(g_res.vga + (y + i) * GAME_SCREEN_W + x, src, 16); int tile_w = 16;
if (x < 0) {
tile_w += x;
src -= x;
x = 0;
}
if (x + tile_w > TILEMAP_SCREEN_W) {
tile_w = TILEMAP_SCREEN_W - x;
}
if (tile_w <= 0) {
return;
}
y = g_vars.screen_tilemap_yoffset + y * 16;
int tile_h = 16;
if (y < 0) {
tile_h += y;
src -= y * 640;
y = 0;
}
if (y + tile_h > TILEMAP_SCREEN_H) {
tile_h = TILEMAP_SCREEN_H - y;
}
if (tile_h <= 0) {
return;
}
for (int i = 0; i < tile_h; ++i) {
memcpy(g_res.vga + (TILEMAP_OFFSET_Y + y + i) * GAME_SCREEN_W + x, src, tile_w);
src += 640; src += 640;
} }
} }
@ -174,7 +171,7 @@ void screen_draw_number(int num, int x, int y, int color) {
y += _offset_y; y += _offset_y;
} }
y += TILEMAP_OFFSET_Y; y += TILEMAP_OFFSET_Y;
if (g_options.amiga_status_bar) { if (g_options.amiga_status_bar || g_res.amiga_data) {
draw_number_amiga(num / 10, x - 8, y - 2); draw_number_amiga(num / 10, x - 8, y - 2);
draw_number_amiga(num % 10, x, y - 2); draw_number_amiga(num % 10, x, y - 2);
} else { } else {
@ -204,7 +201,7 @@ static void decode_graphics(int spr_type, int start, int end) {
struct sys_rect_t r[MAX_SPR_FRAMES]; struct sys_rect_t r[MAX_SPR_FRAMES];
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1); uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
if (data) { if (data) {
const int depth = g_options.amiga_data && (start == 0) ? 3 : 4; const int depth = g_res.amiga_data && (start == 0) ? 3 : 4;
int current_x = 0; int current_x = 0;
int max_w = 0; int max_w = 0;
int current_y = 0; int current_y = 0;
@ -230,7 +227,7 @@ static void decode_graphics(int spr_type, int start, int end) {
max_h = h; max_h = h;
} }
} }
decode_spr(ptr, w, w, h, depth, data, MAX_SPRITESHEET_W, current_x, current_y, g_options.amiga_data); decode_spr(ptr, w, w, h, depth, data, MAX_SPRITESHEET_W, current_x, current_y, g_res.amiga_data);
r[j].x = current_x; r[j].x = current_x;
r[j].y = current_y; r[j].y = current_y;
r[j].w = w; r[j].w = w;
@ -243,7 +240,7 @@ static void decode_graphics(int spr_type, int start, int end) {
assert(max_w <= MAX_SPRITESHEET_W); assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H); assert(current_y + max_h <= MAX_SPRITESHEET_H);
render_unload_sprites(spr_type); render_unload_sprites(spr_type);
const int palette_offset = (g_options.amiga_data && start == 0) ? 16 : 0; const int palette_offset = (g_res.amiga_data && start == 0) ? 16 : 0;
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset); render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset);
free(data); free(data);
} }
@ -273,7 +270,7 @@ void screen_load_graphics() {
free(data); free(data);
} }
// background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout // background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout
if (g_options.amiga_data) { if (g_res.amiga_data) {
static const int BG_TILES_COUNT = 256; static const int BG_TILES_COUNT = 256;
static const int W = 320 / 16; static const int W = 320 / 16;
memcpy(g_res.tmp, g_res.tiles, BG_TILES_COUNT * 16 * 8); memcpy(g_res.tmp, g_res.tiles, BG_TILES_COUNT * 16 * 8);

6
sys.h
View File

@ -25,6 +25,11 @@ struct sys_rect_t {
int w, h; int w, h;
}; };
enum sys_transition_e {
TRANSITION_SQUARE,
TRANSITION_CURTAIN
};
struct sys_t { struct sys_t {
struct input_t input; struct input_t input;
int (*init)(); int (*init)();
@ -36,6 +41,7 @@ struct sys_t {
void (*fade_in_palette)(); void (*fade_in_palette)();
void (*fade_out_palette)(); void (*fade_out_palette)();
void (*update_screen)(const uint8_t *p, int present); void (*update_screen)(const uint8_t *p, int present);
void (*transition_screen)(enum sys_transition_e type, bool open);
void (*process_events)(); void (*process_events)();
void (*sleep)(int duration); void (*sleep)(int duration);
uint32_t (*get_timestamp)(); uint32_t (*get_timestamp)();

View File

@ -192,6 +192,40 @@ static void sdl2_fade_out_palette() {
fade_palette_helper(0); fade_palette_helper(0);
} }
static void sdl2_transition_screen(enum sys_transition_e type, bool open) {
const int step_w = _screen_w / FADE_STEPS;
const int step_h = _screen_h / FADE_STEPS;
SDL_Rect r;
r.x = 0;
r.w = 0;
r.y = 0;
r.h = (type == TRANSITION_CURTAIN) ? _screen_h : 0;
do {
r.x = (_screen_w - r.w) / 2;
if (r.x < 0) {
r.x = 0;
}
r.w += step_w;
if (r.x + r.w > _screen_w) {
r.w = _screen_w - r.x;
}
if (type == TRANSITION_SQUARE) {
r.y = (_screen_h - r.h) / 2;
if (r.y < 0) {
r.y = 0;
}
r.h += step_h;
if (r.y + r.h > _screen_h) {
r.h = _screen_h - r.y;
}
}
SDL_RenderClear(_renderer);
SDL_RenderCopy(_renderer, _texture, &r, &r);
SDL_RenderPresent(_renderer);
SDL_Delay(30);
} while (r.x > 0 && (type == TRANSITION_CURTAIN || r.y > 0));
}
static void sdl2_update_screen(const uint8_t *p, int present) { static void sdl2_update_screen(const uint8_t *p, int present) {
if (_copper_color != -1) { if (_copper_color != -1) {
for (int j = 0; j < _screen_h; ++j) { for (int j = 0; j < _screen_h; ++j) {
@ -459,6 +493,7 @@ struct sys_t g_sys = {
.fade_in_palette = sdl2_fade_in_palette, .fade_in_palette = sdl2_fade_in_palette,
.fade_out_palette = sdl2_fade_out_palette, .fade_out_palette = sdl2_fade_out_palette,
.update_screen = sdl2_update_screen, .update_screen = sdl2_update_screen,
.transition_screen = sdl2_transition_screen,
.process_events = sdl2_process_events, .process_events = sdl2_process_events,
.sleep = sdl2_sleep, .sleep = sdl2_sleep,
.get_timestamp = sdl2_get_timestamp, .get_timestamp = sdl2_get_timestamp,

View File

@ -79,7 +79,7 @@ static void trigger_func_op2(struct object_t *obj) {
obj->ypos16 = obj->ypos >> 4; obj->ypos16 = obj->ypos >> 4;
obj->sprite_type = 1; obj->sprite_type = 1;
obj->yfriction = 0; obj->yfriction = 0;
if (!g_vars.screen_unk1) { if (!g_vars.switch_player_scrolling_flag) {
obj->unk1C = 5; obj->unk1C = 5;
} }
} else if (obj->yvelocity < 0) { } else if (obj->yvelocity < 0) {
@ -90,7 +90,7 @@ static void trigger_func_op2(struct object_t *obj) {
obj->yfriction = 0; obj->yfriction = 0;
} }
obj->unk2F = 0; obj->unk2F = 0;
if (g_vars.screen_unk1) { if (g_vars.switch_player_scrolling_flag) {
obj->special_anim = 18; obj->special_anim = 18;
obj->anim_num = 1; obj->anim_num = 1;
} }
@ -114,7 +114,7 @@ static void trigger_func_op3(struct object_t *obj) {
obj->ypos = obj->ypos16 << 4; obj->ypos = obj->ypos16 << 4;
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin; obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin; obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
g_vars.screen_unk1 = 1; g_vars.switch_player_scrolling_flag = 1;
} }
} }
@ -825,9 +825,6 @@ void triggers_update_tiles1(struct object_t *obj) {
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = p[7]; g_vars.objects[OBJECT_NUM_PLAYER2].data5F = p[7];
} }
screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, 80 + g_vars.level * 32, -12); screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, 80 + g_vars.level * 32, -12);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, 80 + g_vars.level * 32, -12);
g_vars.screen_draw_offset ^= 0x2000;
g_vars.found_music_instrument_flag = 1; g_vars.found_music_instrument_flag = 1;
g_vars.triggers_counter = 0; g_vars.triggers_counter = 0;
play_sound(SOUND_12); play_sound(SOUND_12);
@ -883,19 +880,10 @@ void triggers_update_tiles1(struct object_t *obj) {
++obj->lifes_count; ++obj->lifes_count;
if (!g_vars.two_players_flag) { if (!g_vars.two_players_flag) {
screen_draw_number(obj->lifes_count - 1, 64, 163, 2); screen_draw_number(obj->lifes_count - 1, 64, 163, 2);
g_vars.screen_draw_offset ^= 0x2000; } else if (obj->type == PLAYER_JAKE) {
screen_draw_number(obj->lifes_count - 1, 64, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
} else if (obj->type == 0) {
screen_draw_number(obj->lifes_count - 1, 48, 163, 2); screen_draw_number(obj->lifes_count - 1, 48, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 48, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
} else { } else {
screen_draw_number(obj->lifes_count - 1, 216, 163, 2); screen_draw_number(obj->lifes_count - 1, 216, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
screen_draw_number(obj->lifes_count - 1, 216, 163, 2);
g_vars.screen_draw_offset ^= 0x2000;
} }
} }
} else { } else {
@ -931,7 +919,7 @@ void triggers_update_tiles2(struct object_t *obj) {
obj->anim_num = 1; obj->anim_num = 1;
obj->unk2F = 0; obj->unk2F = 0;
obj->xvelocity = p[3] - 100; obj->xvelocity = p[3] - 100;
obj->xmaxvelocity = ABS(obj->xvelocity); obj->xmaxvelocity = abs(obj->xvelocity);
do_level_player_hit(obj); do_level_player_hit(obj);
} }
obj->trigger3_num = 0; obj->trigger3_num = 0;