2018-12-16 13:34:03 +01:00
|
|
|
|
|
|
|
/* game screens */
|
|
|
|
|
|
|
|
#include "game.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "sys.h"
|
|
|
|
|
|
|
|
struct vars_t g_vars;
|
|
|
|
|
|
|
|
void update_input() {
|
|
|
|
g_sys.process_events();
|
|
|
|
|
|
|
|
g_vars.input_key_left = (g_sys.input.direction & INPUT_DIRECTION_LEFT) != 0 ? 0xFF : 0;
|
|
|
|
g_vars.input_key_right = (g_sys.input.direction & INPUT_DIRECTION_RIGHT) != 0 ? 0xFF : 0;
|
|
|
|
g_vars.input_key_up = (g_sys.input.direction & INPUT_DIRECTION_UP) != 0 ? 0xFF : 0;
|
|
|
|
g_vars.input_key_down = (g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0 ? 0xFF : 0;
|
|
|
|
g_vars.input_key_space = g_sys.input.space ? 0xFF : 0;
|
2022-03-12 23:41:23 +01:00
|
|
|
g_vars.input_key_jump = g_sys.input.jump ? 0xFF : 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
|
|
|
|
g_vars.input_keystate[2] = g_sys.input.digit1;
|
|
|
|
g_vars.input_keystate[3] = g_sys.input.digit2;
|
|
|
|
g_vars.input_keystate[4] = g_sys.input.digit3;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void wait_input(int timeout) {
|
|
|
|
const uint32_t end = g_sys.get_timestamp() + timeout * 10;
|
|
|
|
while (g_sys.get_timestamp() < end) {
|
|
|
|
g_sys.process_events();
|
|
|
|
if (g_sys.input.quit || g_sys.input.space) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_sys.sleep(20);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_splash_screen() {
|
|
|
|
load_file("titus.eat");
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
load_file("tiny.eat");
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void scroll_screen_palette() {
|
2018-12-16 16:46:16 +01:00
|
|
|
++g_vars.level_time;
|
|
|
|
if (g_vars.level_time >= 30) {
|
2018-12-16 13:34:03 +01:00
|
|
|
g_vars.level_time = 0;
|
|
|
|
}
|
2018-12-16 16:46:16 +01:00
|
|
|
const int count = 30 - g_vars.level_time;
|
|
|
|
for (int i = 0; i < count; ++i) {
|
|
|
|
g_sys.set_palette_color(225 + i, g_res.tmp + (225 + g_vars.level_time + i) * 3);
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
2022-03-12 23:41:23 +01:00
|
|
|
g_sys.copy_bitmap(g_res.vga, 320, 200);
|
|
|
|
g_sys.update_screen();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen_scroll_palette(int start, int end, int step, int count) {
|
|
|
|
uint8_t *palette_buffer = g_res.tmp;
|
|
|
|
do {
|
|
|
|
for (int i = start * 3; i < end * 3; ++i) {
|
|
|
|
int color = g_vars.palette_buffer[i];
|
|
|
|
if ((step > 0 && color != palette_buffer[i]) || (step < 0 && color != 0)) {
|
|
|
|
color += step;
|
|
|
|
}
|
|
|
|
g_vars.palette_buffer[i] = color;
|
|
|
|
}
|
|
|
|
g_sys.set_screen_palette(g_vars.palette_buffer + start * 3, start, end - start + 1, 6);
|
2022-03-12 23:41:23 +01:00
|
|
|
g_sys.copy_bitmap(g_res.vga, 320, 200);
|
|
|
|
g_sys.update_screen();
|
2018-12-16 13:34:03 +01:00
|
|
|
g_sys.sleep(20);
|
|
|
|
} while (--count != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen_scroll_palette_pattern1() {
|
|
|
|
do_select_screen_scroll_palette(0x10, 0x4F, -1, 0x19);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen_scroll_palette_pattern2() {
|
|
|
|
do_select_screen_scroll_palette(0x60, 0x9F, -1, 0x19);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen_scroll_palette_pattern3() {
|
|
|
|
do_select_screen_scroll_palette(0x10, 0x4F, 1, 0x19);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen_scroll_palette_pattern4() {
|
|
|
|
do_select_screen_scroll_palette(0x60, 0x9F, 1, 0x19);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_select_screen() {
|
|
|
|
load_file("select.eat");
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
memcpy(g_vars.palette_buffer, g_res.tmp, 256 * 3);
|
|
|
|
do_select_screen_scroll_palette_pattern2();
|
|
|
|
int bl = 2;
|
|
|
|
while (!g_sys.input.quit) {
|
|
|
|
int bh = bl;
|
|
|
|
if (g_sys.input.direction & INPUT_DIRECTION_RIGHT) {
|
|
|
|
g_sys.input.direction &= ~INPUT_DIRECTION_RIGHT;
|
|
|
|
++bl;
|
2018-12-16 16:46:16 +01:00
|
|
|
if (bl > 2) {
|
|
|
|
bl = 2;
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_sys.input.direction & INPUT_DIRECTION_LEFT) {
|
|
|
|
g_sys.input.direction &= ~INPUT_DIRECTION_LEFT;
|
|
|
|
--bl;
|
2018-12-16 16:46:16 +01:00
|
|
|
if (bl < 1) {
|
|
|
|
bl = 1;
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
bh ^= bl;
|
|
|
|
if (bh & 1) {
|
|
|
|
if (bl & 1) {
|
|
|
|
do_select_screen_scroll_palette_pattern4();
|
|
|
|
} else {
|
|
|
|
do_select_screen_scroll_palette_pattern2();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bh & 2) {
|
|
|
|
if (bl & 2) {
|
|
|
|
do_select_screen_scroll_palette_pattern3();
|
|
|
|
} else {
|
|
|
|
do_select_screen_scroll_palette_pattern1();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_sys.input.space) {
|
|
|
|
assert(bl == 1 || bl == 2);
|
|
|
|
g_sys.input.space = 0;
|
|
|
|
g_vars.player = 1 - ((bl & 3) - 1);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
update_input();
|
|
|
|
g_sys.sleep(30);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_difficulty_screen() {
|
|
|
|
char name[16];
|
|
|
|
snprintf(name, sizeof(name), "dif%02d.eat", (g_vars.level >> 3) + 1);
|
|
|
|
load_file(name);
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
wait_input(560);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_number_screen() {
|
|
|
|
load_file("fond.eat");
|
|
|
|
video_draw_string("LEVEL NUMBER", 0x5E0C, 11);
|
|
|
|
char buf[8];
|
|
|
|
snprintf(buf, sizeof(buf), "%02d", g_vars.level);
|
|
|
|
video_draw_string(buf, 0x5E9B, 11);
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
2018-12-16 16:46:16 +01:00
|
|
|
static uint16_t rol16(uint16_t x, int c) {
|
|
|
|
return (x << c) | (x >> (16 - c));
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t get_password(uint16_t x) {
|
|
|
|
x ^= 0xaa31;
|
|
|
|
x *= 0xb297;
|
|
|
|
return rol16(x, 3);
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_password_screen() {
|
|
|
|
load_file("password.eat");
|
|
|
|
uint16_t ax = get_password(g_vars.player * 50 + g_vars.level - 1);
|
|
|
|
char str[5];
|
|
|
|
for (int i = 0; i < 4; ++i, ax <<= 4) {
|
2018-12-16 16:46:16 +01:00
|
|
|
const uint8_t dx = (ax >> 12) + '0';
|
2018-12-16 13:34:03 +01:00
|
|
|
str[i] = (dx <= '9') ? dx : (dx + 7);
|
|
|
|
}
|
|
|
|
str[4] = 0;
|
|
|
|
video_draw_string("STAGE NUMBER", 0x7E96, 11);
|
|
|
|
video_draw_string(str, 0xABB4, 20);
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
scroll_screen_palette();
|
|
|
|
wait_input(64000);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_password_screen() {
|
|
|
|
load_file("password.eat");
|
|
|
|
video_draw_string("ENTER PASSWORD", 0x7E96, 11);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
char str[5] = "0000";
|
|
|
|
video_draw_string(str, 0xABB4, 20);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_menu_screen() {
|
|
|
|
load_file("menu.eat");
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
memset(g_vars.input_keystate, 0, sizeof(g_vars.input_keystate));
|
|
|
|
g_vars.level_time = 0;
|
|
|
|
while (!g_sys.input.quit) {
|
|
|
|
scroll_screen_palette();
|
|
|
|
if (g_vars.input_keystate[2] || g_vars.input_keystate[0x4F] || g_sys.input.space) {
|
|
|
|
g_sys.input.space = 0;
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (g_vars.input_keystate[3] || g_vars.input_keystate[0x50]) {
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
if (g_vars.input_keystate[4] || g_vars.input_keystate[0x51]) {
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
update_input();
|
|
|
|
g_sys.sleep(30);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_options_screen() {
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
load_file("fond.eat");
|
|
|
|
video_draw_string("GAME SPEED", 0x3EE9, 11);
|
|
|
|
video_draw_string("1 FAST", 0x647E, 11);
|
|
|
|
video_draw_string("2 NORMAL", 0x89FE, 11);
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
memset(g_vars.input_keystate, 0, sizeof(g_vars.input_keystate));
|
|
|
|
while (!g_sys.input.quit) {
|
|
|
|
scroll_screen_palette();
|
|
|
|
if (g_vars.input_keystate[2] || g_vars.input_keystate[0x4F]) {
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (g_vars.input_keystate[3] || g_vars.input_keystate[0x50]) {
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
update_input();
|
|
|
|
g_sys.sleep(30);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_game_over_screen() {
|
|
|
|
load_file("fond.eat");
|
|
|
|
video_draw_string("GAME OVER", 0x5E2E, 11);
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
wait_input(64000);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void do_game_win_screen() {
|
|
|
|
load_file("win.eat");
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
load_file("end.eat");
|
2018-12-16 16:44:02 +01:00
|
|
|
video_copy_vga(0xB500);
|
2018-12-16 13:34:03 +01:00
|
|
|
static const int count = 5;
|
|
|
|
static const struct {
|
|
|
|
uint16_t offset;
|
|
|
|
const char *str;
|
|
|
|
} text[] = {
|
|
|
|
{ 0x0F68, "CONGRATULATION" },
|
|
|
|
{ 0x3B34, "YOU HAVE BEATEN" },
|
|
|
|
{ 0x5CE8, "THE EVIL JUKEBOXE" },
|
|
|
|
{ 0x7EB1, "NOW YOU ARE FREE" },
|
|
|
|
{ 0xA072, "AND YOUR CONCERT" },
|
|
|
|
{ 0xC22D, "WILL BE A SUCCESS" },
|
|
|
|
{ 0xFFFF, 0 },
|
|
|
|
{ 0x33BE, "PC CONVERSION" },
|
|
|
|
{ 0x5590, "ERIC ZMIRO" },
|
|
|
|
{ 0x864D, "PC GRAPHICS" },
|
|
|
|
{ 0xA7FC, "DIDIER CARRERE" },
|
|
|
|
{ 0xFFFF, 0 },
|
|
|
|
{ 0x33AF, "ORIGINAL VERSION" },
|
|
|
|
{ 0x5594, "ERIC CAEN" },
|
|
|
|
{ 0x862B, "ORIGINAL GRAPHICS" },
|
|
|
|
{ 0xA835, "BOB" },
|
|
|
|
{ 0xFFFF, 0 },
|
|
|
|
{ 0x33B1, "ORIGINAL MUSICS" },
|
|
|
|
{ 0x559A, "DIMITRI" },
|
|
|
|
{ 0x8653, "PC MUSICS" },
|
|
|
|
{ 0xA7F2, "MICHAEL KNAEPEN" },
|
|
|
|
{ 0xFFFF, 0 },
|
|
|
|
{ 0x5A8F, "THANK YOU" },
|
|
|
|
{ 0x8008, "FOR PLAYING" },
|
|
|
|
{ 0xFFFF, 0 }
|
|
|
|
};
|
|
|
|
int i = 0;
|
|
|
|
for (int j = 0; j < count; ++j) {
|
|
|
|
for (; text[i].str; ++i) {
|
|
|
|
video_draw_string(text[i].str, text[i].offset, 11);
|
|
|
|
}
|
|
|
|
++i;
|
|
|
|
video_copy_vga(0x7D00);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_in_palette();
|
2018-12-16 13:34:03 +01:00
|
|
|
wait_input(64000);
|
2019-06-02 01:50:48 +02:00
|
|
|
g_sys.fade_out_palette();
|
2018-12-16 16:44:02 +01:00
|
|
|
memcpy(g_res.tmp + 768, g_res.background, 64000);
|
2018-12-16 13:34:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void game_main() {
|
|
|
|
play_music(0);
|
|
|
|
do_splash_screen();
|
|
|
|
g_sys.set_screen_palette(common_palette_data, 0, 128, 6);
|
|
|
|
video_load_sprites();
|
2018-12-16 15:28:52 +01:00
|
|
|
g_sys.render_set_sprites_clipping_rect(0, 0, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H);
|
2018-12-16 13:34:03 +01:00
|
|
|
while (!g_sys.input.quit) {
|
|
|
|
update_input();
|
|
|
|
g_vars.level = g_options.start_level;
|
|
|
|
if (g_vars.level == 0) {
|
|
|
|
g_vars.level = 1;
|
|
|
|
}
|
|
|
|
const int ret = do_menu_screen();
|
|
|
|
g_vars.players_table[0].lifes_count = 3;
|
|
|
|
g_vars.players_table[1].lifes_count = 3;
|
|
|
|
if (ret == 0) {
|
|
|
|
break;
|
|
|
|
} else if (ret == 1) {
|
|
|
|
do_select_screen();
|
|
|
|
} else if (ret == 2) {
|
|
|
|
g_vars.level = -1;
|
|
|
|
do_password_screen();
|
|
|
|
if (g_vars.level < 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
++g_vars.level;
|
|
|
|
} else {
|
|
|
|
do_options_screen();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
do_level();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void game_run(const char *data_path) {
|
|
|
|
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
|
|
|
|
sound_init();
|
|
|
|
game_main();
|
|
|
|
sound_fini();
|
|
|
|
res_fini();
|
|
|
|
}
|
|
|
|
|
|
|
|
struct game_t game = {
|
|
|
|
"Blues Brothers : Jukebox Adventure",
|
|
|
|
game_run
|
|
|
|
};
|