blues/p2/game.c

378 lines
9.6 KiB
C

#include <time.h>
#include "game.h"
#include "resource.h"
#include "sys.h"
#include "util.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;
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_programmed_in_1992_screen() {
time_t now;
time(&now);
struct tm *t = localtime(&now);
if (t->tm_year + 1900 < 1996) { /* || t->tm_year + 1900 >= 2067 */
return;
}
video_clear();
g_sys.set_screen_palette(credits_palette_data, 0, 16, 6);
int offset = 0x960;
video_draw_string(offset, 5, "YEAAA > > >");
char str[64];
snprintf(str, sizeof(str), "MY GAME IS STILL WORKING IN %04d <<", 1900 + t->tm_year);
offset += 0x1E0;
video_draw_string(offset, 0, str);
offset = 0x1680;
video_draw_string(offset, 1, "PROGRAMMED IN 1992 ON AT >286 12MHZ>");
offset += 0x1E0;
video_draw_string(offset, 3, "> > > ENJOY OLDIES<<");
g_sys.update_screen(g_res.vga, 1);
wait_input(100);
video_clear();
}
static void do_credits() {
g_sys.set_screen_palette(credits_palette_data, 0, 16, 6);
int offset = 0x140;
video_draw_string(offset, 1, "CODER> DESIGNER AND ARTIST DIRECTOR>");
offset += 0x230;
video_draw_string(offset, 14, "ERIC ZMIRO");
offset += 0x460;
video_draw_string(offset, 4, ">MAIN GRAPHICS AND BACKGROUND>");
offset += 0x230;
video_draw_string(offset, 11, "FRANCIS FOURNIER");
offset += 0x460;
video_draw_string(offset, 9, ">MONSTERS AND HEROS>");
offset += 0x230;
video_draw_string(offset, 11, "LYES BELAIDOUNI");
offset = 0x1770;
video_draw_string(offset, 15, "THANKS TO");
offset = 0x1A40;
video_draw_string(offset, 2, "CRISTELLE> GIL ESPECHE AND CORINNE>");
offset += 0x1E0;
video_draw_string(offset, 0, "SEBASTIEN BECHET AND OLIVIER AKA DELTA>");
g_sys.update_screen(g_res.vga, 1);
}
static void update_screen_img(const uint8_t *src, int present) {
const int size = GAME_SCREEN_W * GAME_SCREEN_H;
if (size < 64000) {
return;
} else if (size == 64000) {
g_sys.update_screen(src, present);
} else {
memset(g_res.vga, 0, size);
const int y_offs = (GAME_SCREEN_H - 200) / 2;
const int x_offs = (GAME_SCREEN_W - 320) / 2;
for (int y = 0; y < 200; ++y) {
memcpy(g_res.vga + (y_offs + y) * GAME_SCREEN_W + x_offs, src + y * 320, 320);
}
g_sys.update_screen(g_res.vga, present);
}
}
static void do_titus_screen() {
uint8_t *data = load_file("TITUS.SQZ");
if (data) {
g_sys.set_screen_palette(data, 0, 256, 6);
update_screen_img(data + 768, 0);
g_sys.fade_in_palette();
wait_input(70);
g_sys.fade_out_palette();
free(data);
}
}
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 diff = target[i] - al;
if (diff != 0) {
if (abs(diff) < 2) {
flag = true;
current[i] = target[i];
} else {
if (target[i] < al) {
current[i] = al - 2;
} else {
current[i] = al + 2;
}
}
}
}
return flag;
}
static void do_present_screen() {
uint8_t *data = load_file("PRESENT.SQZ");
if (data) {
if (g_uncompressed_size == 65536 + 768) { /* demo version */
g_sys.set_screen_palette(data, 0, 256, 6);
update_screen_img(data + 768, 0);
g_sys.fade_in_palette();
} else {
memmove(data + 768, data + 0x1030 * 16, 93 * 320);
g_sys.set_screen_palette(data, 0, 256, 6);
update_screen_img(data + 768, 0);
g_sys.fade_in_palette();
uint8_t palette[256 * 3];
memcpy(palette, data, 256 * 3);
while (fade_palettes(present_palette_data, palette) && !g_sys.input.quit) {
g_sys.set_screen_palette(palette, 0, 256, 6);
update_screen_img(data + 768, 1);
wait_input(10);
}
}
g_sys.fade_out_palette();
free(data);
}
}
static const uint8_t joystick_palette_data[] = {
0x08,0x14,0x22,0x10,0x00,0x00,0x18,0x00,0x00,0x20,0x00,0x08,0x06,0x0F,0x1A,0x28,
0x10,0x08,0x28,0x18,0x08,0x30,0x20,0x08,0x30,0x28,0x08,0x38,0x30,0x10,0x38,0x30,
0x18,0x38,0x30,0x20,0x38,0x30,0x28,0x38,0x30,0x30,0x38,0x38,0x38,0x00,0x00,0x00
};
static void do_demo_screen() {
uint8_t *data = load_file("JOYSTICK.SQZ");
if (data) {
video_copy_img(data);
g_sys.set_screen_palette(joystick_palette_data, 0, 16, 6);
update_screen_img(g_res.background, 0);
g_sys.fade_in_palette();
free(data);
wait_input(1000);
}
}
static void do_castle_screen() {
uint8_t *data = load_file("CASTLE.SQZ");
if (data) {
g_sys.set_screen_palette(data, 0, 256, 6);
update_screen_img(data + 768, 0);
g_sys.fade_in_palette();
free(data);
wait_input(1000);
}
}
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);
update_screen_img(data + 768, 0);
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) {
g_sys.input.space = 0;
g_sys.fade_out_palette();
break;
}
if (g_vars.input.keystate[3] || g_vars.input.keystate[0x50]) {
g_sys.fade_out_palette();
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() {
}
void input_check_ctrl_alt_e() {
if (g_vars.input.keystate[0x1D] && g_vars.input.keystate[0x38] && g_vars.input.keystate[0x12]) {
do_photos_screen();
}
}
void input_check_ctrl_alt_w() {
if (g_vars.input.keystate[0x1D] && g_vars.input.keystate[0x38] && g_vars.input.keystate[0x11]) {
do_credits();
wait_input(60);
}
}
void do_theend_screen() {
uint8_t *data = load_file("THEEND.SQZ");
if (data) {
g_sys.set_screen_palette(data, 0, 256, 6);
update_screen_img(data + 768, 0);
g_sys.fade_in_palette();
free(data);
wait_input(1000);
}
time_t now;
time(&now);
struct tm *t = localtime(&now);
if (t->tm_year + 1900 < 1994) {
return;
}
do_photos_screen();
}
uint32_t timer_get_counter() {
const uint32_t current = g_sys.get_timestamp();
return ((current - g_vars.starttime) * 1193182 / 0x4000) / 1000;
}
void random_reset() {
g_vars.random.a = 5;
g_vars.random.b = 34;
g_vars.random.c = 134;
g_vars.random.d = 58765;
}
uint8_t random_get_number() {
g_vars.random.d += g_vars.random.a;
g_vars.random.a += 3 + (g_vars.random.d >> 8);
g_vars.random.b += g_vars.random.c;
g_vars.random.b *= 2;
g_vars.random.b += g_vars.random.a;
g_vars.random.c ^= g_vars.random.a;
g_vars.random.c ^= g_vars.random.b;
return g_vars.random.b;
}
static uint16_t ror16(uint16_t x, int c) {
return (x >> c) | (x << (16 - c));
}
uint16_t random_get_number2() {
const uint16_t x = g_vars.random.e + 0x9248;
g_vars.random.e = ror16(x, 3);
return g_vars.random.e;
}
static uint16_t rol16(uint16_t x, int c) {
return (x << c) | (x >> (16 - c));
}
/* original code returns a machine specific value, based on BIOS and CPU */
uint16_t random_get_number3(uint16_t x) {
x ^= 0x55a3;
x *= 0xb297; /* to match dosbox */
return rol16(x, 3);
}
static void game_run(const char *data_path) {
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
sound_init();
video_convert_tiles(g_res.uniondat, g_res.unionlen);
g_vars.level_num = g_options.start_level;
do_programmed_in_1992_screen();
if (!g_sys.input.space && !g_sys.input.quit) {
do_titus_screen();
play_music(3);
do_present_screen();
}
g_sys.render_set_sprites_clipping_rect(0, 0, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H);
g_vars.random.e = 0x1234;
g_vars.starttime = g_sys.get_timestamp();
while (!g_sys.input.quit) {
if (1) {
g_vars.player_lifes = 2;
g_vars.player_bonus_letters_mask = 0;
g_vars.player_club_power = 20;
g_vars.player_club_type = 0;
if (g_res.dos_demo) {
do_demo_screen();
}
while (do_menu()) {
do_menu2();
}
if (g_sys.input.quit) {
break;
}
}
uint8_t level_num;
do {
level_num = g_vars.level_num;
if (g_vars.level_num >= 8 && g_vars.level_num < 10 && 0 /* !g_vars.level_expert_flag */ ) {
do_castle_screen();
break;
}
do_level();
print_debug(DBG_GAME, "previous level %d current %d", level_num, g_vars.level_num);
} while (!g_res.dos_demo && g_vars.level_num != level_num);
}
sound_fini();
res_fini();
}
struct game_t game = {
"Prehistorik 2",
game_run
};