Import blues from b21d8347

This commit is contained in:
Gregory Montoir 2019-05-29 08:07:54 +08:00
parent 6a5f7c4646
commit 924b0f3438
12 changed files with 349 additions and 138 deletions

View File

@ -64,6 +64,9 @@ void decode_amiga_gfx(uint8_t *dst, int dst_pitch, int w, int h, int depth, cons
color |= 1 << bit;
}
}
if (palette_mask == 0 && color == 0) {
continue;
}
dst[x * 16 + i] = palette_mask | color;
}
}

View File

@ -75,7 +75,9 @@ static void do_select_player() {
const int color_rgb = 2;
const int colors_count = 25;
load_img(g_res.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W, g_options.cga_colors ? 1 : -1);
if (g_res.spr_count <= SPRITES_COUNT) {
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, 0);
}
screen_clear_sprites();
do {
update_input();

View File

@ -42,6 +42,24 @@ static void add_game_sprite(int x, int y, int frame, int xflip) {
}
void screen_add_sprite(int x, int y, int frame) {
if (g_res.amiga_data) {
switch (frame) {
case 125: {
extern const uint8_t spr71a6_amiga[];
static const int w = 16;
static const int h = 6;
decode_amiga_gfx(g_res.vga + (y - h) * GAME_SCREEN_W + (x - w / 2), GAME_SCREEN_W, w, h, 4, spr71a6_amiga, w, 0x0, 0xFFFF);
}
return;
case 126: {
extern const uint8_t spr71da_amiga[];
static const int w = 48;
static const int h = 34;
decode_amiga_gfx(g_res.vga + (y - h) * GAME_SCREEN_W + (x - w / 2), GAME_SCREEN_W, w, h, 4, spr71da_amiga, w, 0x0, 0xFFFF);
}
return;
}
}
add_game_sprite(x, y, frame, 0);
}

View File

@ -3,6 +3,7 @@
#include "game.h"
#include "resource.h"
#include "sys.h"
#include "util.h"
#include <libmodplug/modplug.h>
@ -34,10 +35,10 @@ static const struct {
// Amiga, ExoticA
static const char *_modules[] = {
"ALMOST", "mod.almost",
"GUNN", "mod.bluesgunnbest",
"EVERY", "mod.every",
"SHOT", "mod.shot"
"almost", "mod.almost",
"gunn", "mod.bluesgunnbest",
"every", "mod.every",
"shot", "mod.shot"
};
struct mixerchannel_t {
@ -119,31 +120,37 @@ void play_music(int num) {
// append samples to the end of the buffer
static const int SONG_INFO_LEN = 20;
static const int NUM_SAMPLES = 8;
struct {
char *name;
int size;
} samples[8];
int samples_size = 0;
int offset = SONG_INFO_LEN;
for (int i = 0; i < NUM_SAMPLES; ++i, offset += 30) {
const char *sample_name = (const char *)&buf[offset];
if (sample_name[0]) {
samples_size += READ_BE_UINT16(&buf[offset + 22]) * 2;
}
samples[i].name = (char *)&buf[offset];
samples[i].size = READ_BE_UINT16(&buf[offset + 22]) * 2;
string_lower(samples[i].name);
samples_size += samples[i].size;
}
buf = (uint8_t *)realloc(buf, size + samples_size);
if (buf) {
offset = SONG_INFO_LEN;
for (int i = 0; i < NUM_SAMPLES; ++i, offset += 30) {
const char *sample_name = (const char *)&buf[offset];
const int sample_size = READ_BE_UINT16(&buf[offset + 22]) * 2;
if (sample_name[0]) {
int sample_slot = fio_open(sample_name, 0);
if (!(sample_slot < 0)) {
fio_read(sample_slot, buf + size, sample_size);
size += sample_size;
}
memset(buf + size, 0, samples_size);
for (int i = 0; i < NUM_SAMPLES; ++i) {
if (samples[i].size != 0) {
if (samples[i].name[0]) {
const int sample_slot = fio_open(samples[i].name, 0);
if (sample_slot < 0) {
print_warning("Unable to open instrument '%s'", samples[i].name);
} else {
fio_read(sample_slot, buf + size, samples[i].size);
fio_close(sample_slot);
}
}
size += samples[i].size;
}
}
_mpf = ModPlug_Load(buf, size);
free(buf);
}

View File

@ -1807,3 +1807,63 @@ const uint8_t dither_cga_table[] = {
0x00,0x00,0x00,0x00,0xAA,0xAA,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x55,0x55,
0x55,0x55,0x00,0x00,0xAA,0xAA,0x00,0x00,0xFF,0xFF,0xAA,0xAA,0x55,0x55,0xFF,0xFF
};
const uint8_t spr71a6_amiga[] = {
0x03,0x80,0x07,0xc0,0x07,0xe0,0x07,0xe0,0x03,0xe0,0x01,0xc0,0x00,0x00,0x00,0x00,
0x00,0x20,0x00,0x20,0x00,0x60,0x01,0xc0,0x03,0x80,0x07,0xc0,0x07,0xc0,0x07,0xc0,
0x03,0x80,0x00,0x00,0x03,0x80,0x07,0xc0,0x07,0xe0,0x07,0xe0,0x03,0xe0,0x01,0xc0,
0x00,0x22,0x00,0x30
};
const uint8_t spr71da_amiga[] = {
0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x07,
0x80,0x00,0x00,0x00,0x00,0x78,0x07,0x00,0x00,0x00,0x07,0x80,0x7f,0x00,0x00,0x00,
0x78,0x07,0xf8,0x00,0x00,0x03,0x80,0x7f,0x87,0x00,0x00,0x00,0x07,0xf8,0x7b,0x00,
0x00,0x00,0x7f,0x87,0x8b,0x00,0x00,0x03,0xf8,0x78,0x0b,0x00,0x00,0x03,0x87,0x80,
0x0b,0x00,0x00,0x00,0x78,0x00,0x0b,0x00,0x00,0x03,0xc0,0x00,0x0b,0x00,0x00,0x02,
0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,
0x00,0x02,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,
0x0b,0x00,0x00,0x02,0xc0,0x00,0xfb,0x00,0x00,0x02,0xc0,0x01,0x0f,0x00,0x00,0x02,
0xc0,0x02,0x07,0x00,0x00,0x02,0xc0,0x04,0x7b,0x00,0x00,0x3e,0xc0,0x04,0xff,0x00,
0x00,0x43,0xc0,0x05,0xff,0x00,0x00,0x81,0xc0,0x05,0xfd,0x00,0x01,0x1e,0xc0,0x07,
0xf9,0x00,0x01,0x3f,0xc0,0x03,0x62,0x00,0x01,0x7f,0xc0,0x01,0x84,0x00,0x01,0x7f,
0x40,0x00,0xf8,0x00,0x01,0xfe,0x40,0x00,0x00,0x00,0x00,0xdc,0x80,0x00,0x00,0x00,
0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x07,0x00,0x00,0x00,0x00,0x00,0x79,0x00,0x00,0x00,0x00,0x07,0x80,0x00,0x00,0x00,
0x00,0x78,0x07,0x00,0x00,0x00,0x07,0x80,0x7f,0x00,0x00,0x00,0x78,0x07,0xf8,0x00,
0x00,0x03,0x80,0x7f,0x87,0x00,0x00,0x02,0x07,0xf8,0x7b,0x00,0x00,0x00,0x7f,0x87,
0x8f,0x00,0x00,0x03,0xf8,0x78,0x0b,0x00,0x00,0x03,0x87,0x80,0x0b,0x00,0x00,0x00,
0x78,0x00,0x0b,0x00,0x00,0x03,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,
0x00,0x03,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,
0x0b,0x00,0x00,0x02,0xc0,0x00,0x0b,0x00,0x00,0x02,0xc0,0x00,0x0f,0x00,0x00,0x02,
0xc0,0x00,0xfb,0x00,0x00,0x02,0xc0,0x01,0xbf,0x00,0x00,0x02,0xc0,0x02,0x0f,0x00,
0x00,0x03,0xc0,0x06,0x7b,0x00,0x00,0x3e,0xc0,0x04,0xff,0x00,0x00,0x6f,0xc0,0x07,
0xff,0x00,0x00,0x83,0xc0,0x05,0xfd,0x00,0x01,0x9e,0xc0,0x07,0xf9,0x00,0x01,0x3f,
0xc0,0x03,0x62,0x00,0x01,0xff,0xc0,0x01,0x84,0x00,0x01,0x7f,0x40,0x00,0xf8,0x00,
0x01,0xfe,0x40,0x00,0x00,0x00,0x00,0xdc,0x80,0x00,0x00,0x00,0x00,0x61,0x00,0x00,
0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x7f,0x00,0x00,0x00,0x00,0x07,0xf8,0x00,
0x00,0x00,0x00,0x7f,0x80,0x00,0x00,0x00,0x07,0xf8,0x07,0x00,0x00,0x00,0x7f,0x80,
0x78,0x00,0x00,0x01,0xf8,0x07,0x84,0x00,0x00,0x03,0x80,0x78,0x00,0x00,0x00,0x00,
0x07,0x80,0x04,0x00,0x00,0x00,0x78,0x00,0x04,0x00,0x00,0x03,0x80,0x00,0x04,0x00,
0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,
0x04,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x04,0x00,0x00,0x01,
0x00,0x00,0x04,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x04,0x00,
0x00,0x01,0x00,0x00,0x40,0x00,0x00,0x01,0x00,0x01,0x70,0x00,0x00,0x00,0x00,0x00,
0x84,0x00,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x5c,
0x00,0x02,0x02,0x00,0x00,0x21,0x00,0x00,0x06,0x00,0x00,0xc0,0x00,0x00,0x9c,0x00,
0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x01,0x80,0x00,
0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x1e,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,
0x00,0x00,0x00,0x07,0xf8,0x00,0x00,0x00,0x00,0x7f,0x87,0x00,0x00,0x00,0x07,0xf8,
0x7f,0x00,0x00,0x00,0x7f,0x87,0xf8,0x00,0x00,0x03,0xf8,0x7f,0x87,0x00,0x00,0x01,
0x87,0xf8,0x7b,0x00,0x00,0x00,0x7f,0x87,0x8b,0x00,0x00,0x03,0xf8,0x78,0x0f,0x00,
0x00,0x03,0x87,0x80,0x0f,0x00,0x00,0x00,0x78,0x00,0x0f,0x00,0x00,0x03,0xc0,0x00,
0x0f,0x00,0x00,0x02,0xc0,0x00,0x0f,0x00,0x00,0x02,0xc0,0x00,0x0f,0x00,0x00,0x03,
0xc0,0x00,0x0f,0x00,0x00,0x03,0xc0,0x00,0x0f,0x00,0x00,0x03,0xc0,0x00,0x0f,0x00,
0x00,0x03,0xc0,0x00,0x0b,0x00,0x00,0x03,0xc0,0x00,0xfb,0x00,0x00,0x03,0xc0,0x01,
0x4f,0x00,0x00,0x03,0xc0,0x03,0x87,0x00,0x00,0x02,0xc0,0x05,0x7b,0x00,0x00,0x3e,
0xc0,0x06,0xff,0x00,0x00,0x53,0xc0,0x05,0xff,0x00,0x00,0xe1,0xc0,0x05,0xfd,0x00,
0x01,0x5e,0xc0,0x07,0xf9,0x00,0x01,0xbf,0xc0,0x03,0x62,0x00,0x01,0x7f,0xc0,0x01,
0x84,0x00,0x01,0x7f,0x40,0x00,0xf8,0x00,0x01,0xfe,0x40,0x00,0x00,0x00,0x00,0xdc,
0x80,0x00,0x00,0x00,0x00,0x61,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,
0x00,0x22,0x00,0xa0
};

View File

@ -37,7 +37,7 @@ static void do_programmed_in_1992_screen() {
time_t now;
time(&now);
struct tm *t = localtime(&now);
if (t->tm_year + 1900 < 1996) {
if (t->tm_year + 1900 < 1996) { /* || t->tm_year + 1900 >= 2067 */
return;
}
g_sys.set_screen_palette(credits_palette_data, 0, 16, 6);
@ -127,9 +127,6 @@ static void do_menu() {
fade_out_palette();
break;
}
if (g_vars.input.keystate[4] || g_vars.input.keystate[0x51]) {
break;
}
g_sys.sleep(30);
}
}

View File

@ -10,6 +10,7 @@ extern struct options_t g_options;
#define TILEMAP_SCREEN_W GAME_SCREEN_W
#define TILEMAP_SCREEN_H (GAME_SCREEN_H - PANEL_H)
#define TILEMAP_SCROLL_W 64
#define CHEATS_NO_HIT (1 << 0)
#define CHEATS_UNLIMITED_LIFES (1 << 1)
@ -35,6 +36,11 @@ struct club_projectile_t {
int16_t y_velocity; // 0xE
};
struct monster_t {
void *ref; // 0x6
uint8_t unkE; // 0xE
};
struct thing_t {
void *ref; // 0x9
int16_t counter; // 0xC
@ -49,6 +55,7 @@ struct object_t {
union { // 0x9 - 0x10
struct player_t p; /* objects[1] */
struct club_projectile_t c; /* objects[2..5] */
struct monster_t m; /* objects[11..22] */
struct thing_t t;
} data;
uint8_t hit_counter; // 0x11
@ -104,6 +111,9 @@ struct vars_t {
uint16_t level_draw_counter;
uint8_t shake_screen_counter;
uint16_t shake_screen_voffset;
uint8_t player_lifes;
uint8_t player_energy;
uint8_t player_death_flag;
@ -129,11 +139,9 @@ struct vars_t {
uint8_t player_club_anim_duration;
bool player_using_club_flag;
uint16_t player_update_counter;
uint8_t player_platform_counter;
uint8_t player_current_anim_type;
uint8_t player_tile_flags;
int16_t level_current_bonus_x_pos, level_current_bonus_y_pos, level_current_bonus_spr_num;
uint8_t level_items_count_tbl[140]; /* bonuses and items collected in the level */
uint8_t level_items_total_count;
uint8_t level_bonuses_count_tbl[80];
@ -152,8 +160,8 @@ struct vars_t {
bool tilemap_adjust_player_pos_flag;
uint8_t level_noscroll_flag;
int16_t tilemap_yscroll_diff;
uint16_t tilemap_x, tilemap_y;
uint16_t tilemap_prev_x, tilemap_prev_y;
int16_t tilemap_x, tilemap_y;
int16_t tilemap_prev_x, tilemap_prev_y;
int8_t tilemap_scroll_dx, tilemap_scroll_dy;
uint8_t tilemap_h;
uint16_t tilemap_size; /* tilemap size h*256 */
@ -169,6 +177,10 @@ struct vars_t {
uint8_t tilemap_redraw_flag2; /* tilemap needs redraw */
uint8_t tilemap_redraw_flag1; /* force redraw even if tilemap origin did not change */
struct {
int16_t x_pos, y_pos;
uint16_t spr_num;
} current_bonus; /* bonus added */
struct {
uint16_t value;
uint16_t counter;

View File

@ -262,7 +262,7 @@ static void level_update_tilemap() {
g_vars.animated_tiles_flag = 0;
uint16_t offset = (g_vars.tilemap_y << 8) | g_vars.tilemap_x;
for (int y = 0; y < (TILEMAP_SCREEN_H / 16) + 1; ++y) {
for (int x = 0; x < TILEMAP_SCREEN_W / 16; ++x) {
for (int x = 0; x < (TILEMAP_SCREEN_W / 16) + 1; ++x) {
const uint8_t tile_num = level_get_tile(offset + x);
g_vars.tile_attr2_flags |= g_res.level.tile_attributes2[tile_num];
if (_redraw_tilemap || g_vars.animated_tile_flag_tbl[tile_num] != 0) {
@ -305,18 +305,6 @@ static void level_draw_tilemap() {
}
static bool level_adjust_hscroll_left() {
if (!g_options.dos_scrolling && 0) {
if (g_vars.tilemap_scroll_dx >= 0) {
return false;
}
g_vars.tilemap_scroll_dx += 4;
--g_vars.tilemap_x;
if (g_vars.tilemap_x < 0) {
g_vars.tilemap_x = 0;
g_vars.tilemap_scroll_dx = 0;
}
return true;
}
if (g_vars.tilemap_x == 0) {
return true;
}
@ -324,22 +312,18 @@ static bool level_adjust_hscroll_left() {
return false;
}
static bool level_adjust_hscroll_right() {
if (!g_options.dos_scrolling && 0) {
if (g_vars.tilemap_scroll_dx < 4) {
return false;
}
g_vars.tilemap_scroll_dx -= 4;
++g_vars.tilemap_x;
return true;
}
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);
} else {
end_x = g_res.level.tilemap_w;
}
if (g_vars.tilemap_x >= end_x) {
return end_x;
}
static bool level_adjust_hscroll_right() {
if (g_vars.tilemap_x >= tilemap_end_xpos()) {
return true;
}
++g_vars.tilemap_x;
@ -347,6 +331,30 @@ static bool level_adjust_hscroll_right() {
}
static void level_adjust_x_scroll() {
if (!g_options.dos_scrolling && g_vars.level_noscroll_flag == 0) {
const int x1 = TILEMAP_SCROLL_W * 2;
const int x2 = TILEMAP_SCREEN_W - TILEMAP_SCROLL_W * 2;
int tilemap_xpos = (g_vars.tilemap_x << 4) + g_vars.tilemap_scroll_dx;
const int player_xpos = g_vars.objects_tbl[1].x_pos - tilemap_xpos;
if (player_xpos > x2) {
tilemap_xpos += (player_xpos - x2);
const int tilemap_xend = tilemap_end_xpos() << 4;
if (tilemap_xpos > tilemap_xend) {
tilemap_xpos = tilemap_xend;
}
} else if (player_xpos < x1) {
tilemap_xpos += (player_xpos - x1);
if (tilemap_xpos < 0) {
tilemap_xpos = 0;
}
}
g_vars.tilemap_x = (tilemap_xpos >> 4);
g_vars.tilemap_scroll_dx = (tilemap_xpos & 15);
g_vars.tilemap_scroll_dx &= ~1;
g_vars.level_xscroll_center_flag = 0;
return;
}
const int x_pos = (g_vars.objects_tbl[1].x_pos >> 4) - g_vars.tilemap_x;
if (x_pos >= (TILEMAP_SCREEN_W / 16) || g_vars.level_force_x_scroll_flag != 0 || g_vars.objects_tbl[1].x_velocity != 0) {
if (g_vars.level_xscroll_center_flag != 0) {
@ -645,7 +653,7 @@ static void level_update_tile_attr1_helper(uint16_t offset) {
if (dy >= 32 && g_vars.objects_tbl[1].data.p.y_velocity >= 80) {
g_vars.player_prev_y_pos = g_vars.objects_tbl[1].y_pos;
if (g_vars.player_jumping_counter >= 20 && g_vars.objects_tbl[1].data.p.y_velocity > 160) {
g_vars.player_platform_counter = 8;
g_vars.shake_screen_counter = 8;
}
if (g_vars.player_jumping_counter > 10) {
if ((g_res.level.scrolling_mask & 1) == 0) {
@ -978,11 +986,11 @@ static void level_add_object23_bonus(int x_vel, int y_vel, int count) {
for (int i = 0; i < 32; ++i) {
struct object_t *obj = &g_vars.objects_tbl[23 + i];
if (obj->spr_num == 0xFFFF) {
obj->spr_num = g_vars.level_current_bonus_spr_num;
obj->spr_num = g_vars.current_bonus.spr_num;
obj->hit_counter = 0;
obj->data.t.counter = 198;
obj->x_pos = g_vars.level_current_bonus_x_pos;
obj->y_pos = g_vars.level_current_bonus_y_pos;
obj->x_pos = g_vars.current_bonus.x_pos;
obj->y_pos = g_vars.current_bonus.y_pos;
obj->x_velocity = x_vel;
obj->data.p.y_velocity = y_vel;
x_vel = -x_vel;
@ -1090,8 +1098,8 @@ static bool level_handle_bonuses_found(struct object_t *obj, struct level_bonus_
if (bonus->count & 0x80) {
return false;
}
g_vars.level_current_bonus_x_pos = (pos & 0xFF) << 4;
g_vars.level_current_bonus_y_pos = (pos >> 8) << 4;
g_vars.current_bonus.x_pos = (pos & 0xFF) << 4;
g_vars.current_bonus.y_pos = (pos >> 8) << 4;
int num = 0;
while (1) {
num = random_get_number() & 7;
@ -1099,8 +1107,8 @@ static bool level_handle_bonuses_found(struct object_t *obj, struct level_bonus_
break;
}
}
g_vars.level_current_bonus_spr_num = 110 + num;
g_vars.level_current_bonus_y_pos -= 112;
g_vars.current_bonus.spr_num = 110 + num;
g_vars.current_bonus.y_pos -= 112;
level_add_object23_bonus(0, 0, 1);
} else {
static uint8_t draw_counter = 0;
@ -1109,30 +1117,30 @@ static bool level_handle_bonuses_found(struct object_t *obj, struct level_bonus_
if (diff < 6) {
return true;
}
g_vars.level_current_bonus_x_pos = (pos & 0xFF) << 4;
g_vars.level_current_bonus_y_pos = (pos >> 8) << 4;
g_vars.current_bonus.x_pos = (pos & 0xFF) << 4;
g_vars.current_bonus.y_pos = (pos >> 8) << 4;
int ax, count = 1;
if (bonus->count & 0x40) {
if (bonus->count == 64) {
bonus->count = 0;
if (g_vars.level_num == 7 || g_vars.level_num == 6) {
g_vars.level_current_bonus_spr_num = 300;
g_vars.current_bonus.spr_num = 300;
level_add_object23_bonus(32, -48, 2);
g_vars.level_current_bonus_spr_num = 229;
g_vars.current_bonus.spr_num = 229;
count = 4;
} else {
g_vars.level_current_bonus_spr_num = 229;
g_vars.current_bonus.spr_num = 229;
count = 1;
}
} else {
if (g_vars.level_num == 7 || g_vars.level_num == 6) {
g_vars.level_current_bonus_spr_num = 300;
g_vars.current_bonus.spr_num = 300;
level_add_object23_bonus(48, -96, 4);
}
goto decrement_bonus;
}
} else {
g_vars.level_current_bonus_spr_num = level_get_random_bonus_spr_num();
g_vars.current_bonus.spr_num = level_get_random_bonus_spr_num();
}
ax = 48;
if (obj < &g_vars.objects_tbl[1]) {
@ -1408,61 +1416,60 @@ static void level_update_objects_decors() {
}
if ((trigger->flags & 15) == 8) {
g_vars.level_current_object_decor_x_pos = 0;
trigger->y_pos -= trigger->unkB;
if (trigger->state == 0) {
int a = trigger->unkB - 8;
trigger->y_pos -= trigger->type8.y_delta;
if (trigger->type8.state == 0) {
int a = trigger->type8.y_delta - 8;
if (a < 0) {
a = 0;
trigger->unk7 = 0;
trigger->type8.unk7 = 0;
}
trigger->unkB = a;
trigger->type8.y_delta = a;
}
if (trigger->flags & 0x40) {
if (trigger->unk7 != 0 && --trigger->counter == 0) {
trigger->state = 1;
trigger->unk7 = 0;
if (trigger->type8.unk7 != 0 && --trigger->type8.counter == 0) {
trigger->type8.state = 1;
trigger->type8.unk7 = 0;
}
} else {
if (trigger->state == 1) {
int y = trigger->unk7;
if (trigger->type8.state == 1) {
int y = trigger->type8.unk7;
if (y < 192) {
trigger->unk7 += 8;
trigger->type8.unk7 += 8;
}
y >>= 4;
g_vars.level_current_object_decor_y_pos = y;
trigger->unkB += y;
int bx = trigger->x_pos >> 4;
int dx = (trigger->y_pos + trigger->unkB) >> 4;
int ax = g_vars.tilemap_h - 1 - dx;
if (ax < 0) {
ax = -ax;
if (ax >= 3) {
trigger->state = 2;
trigger->counter = 22;
trigger->type8.y_delta += y;
const int tile_x = trigger->x_pos >> 4;
const int tile_y = (trigger->y_pos + trigger->type8.y_delta) >> 4;
const int y2 = g_vars.tilemap_h - 1 - tile_y;
if (y2 < 0) {
if ((-y2) >= 3) {
trigger->type8.state = 2;
trigger->type8.counter = 22;
}
} else {
const uint8_t tile_num = level_get_tile((dx << 8) | bx);
const uint8_t tile_num = level_get_tile((tile_y << 8) | tile_x);
const uint8_t tile_attr1 = g_res.level.tile_attributes1[tile_num];
if (tile_attr1 != 0 && tile_attr1 != 6) {
trigger->state = 2;
trigger->counter = 22;
trigger->type8.state = 2;
trigger->type8.counter = 22;
}
}
} else {
if (trigger->state == 2 && (trigger->flags & 0x40) == 0 && --trigger->counter == 0) {
trigger->state = 0;
trigger->counter = trigger->unk9;
if (trigger->type8.state == 2 && (trigger->flags & 0x40) == 0 && --trigger->type8.counter == 0) {
trigger->type8.state = 0;
trigger->type8.counter = trigger->type8.unk9;
}
}
}
trigger->y_pos += trigger->unkB;
trigger->y_pos += trigger->type8.y_delta;
} else {
g_vars.level_current_object_decor_x_pos = 0;
g_vars.level_current_object_decor_y_pos = 0;
if (trigger->unkE != 0 || trigger->unk7 < 0 || (trigger->flags & 0xC0) != 0) {
if (trigger->unk7 > trigger->unkE) {
if (trigger->unkE != 0 || trigger->other.unk7 < 0 || (trigger->flags & 0xC0) != 0) {
if (trigger->other.unk7 > trigger->unkE) {
++trigger->unkE;
} else if (trigger->unk7 < trigger->unkE) {
} else if (trigger->other.unk7 < trigger->unkE) {
--trigger->unkE;
}
int al = trigger->unkE;
@ -1494,7 +1501,13 @@ static void level_update_objects_decors() {
trigger->x_pos += al;
g_vars.level_current_object_decor_y_pos = (int8_t)dl;
trigger->y_pos += dl;
if (trigger->unk7 == trigger->unkE) {
if (trigger->other.unk7 == trigger->unkE) {
int16_t ax = trigger->other.unkC + 1;
if (trigger->other.unkA == ax) {
trigger->other.unk7 = -trigger->other.unk7;
ax = 0;
}
trigger->other.unkC = ax;
}
}
}
@ -2109,8 +2122,8 @@ update_pos:
if (g_vars.player_club_anim_duration > 0) {
--g_vars.player_club_anim_duration;
}
if (g_vars.player_platform_counter > 0) {
--g_vars.player_platform_counter;
if (g_vars.shake_screen_counter > 0) {
--g_vars.shake_screen_counter;
}
if (g_vars.restart_level_flag > 0) {
--g_vars.restart_level_flag;
@ -2159,7 +2172,7 @@ static void level_update_player_collision() {
if (!level_objects_collide(obj, obj_player)) {
continue;
}
g_vars.level_current_bonus_spr_num = obj->spr_num;
g_vars.current_bonus.spr_num = obj->spr_num;
const int num = (obj->spr_num & 0x1FFF) - 53;
obj->spr_num = 0xFFFF;
if (num == 226) {
@ -2235,10 +2248,10 @@ static void level_update_player_collision() {
int x = 32;
if ((random_get_number() & 1) != 0) {
x = -x;
g_vars.player_platform_counter = 7;
g_vars.shake_screen_counter = 7;
}
obj->x_velocity = x;
obj->spr_num = g_vars.level_current_bonus_spr_num;
obj->spr_num = g_vars.current_bonus.spr_num;
} else {
const int index = num - 57;
++g_vars.level_items_count_tbl[index];
@ -2268,16 +2281,16 @@ static void level_update_player_collision() {
g_vars.objects_tbl[1].hit_counter = 44;
g_vars.objects_tbl[1].data.p.special_anim_num = 0;
g_vars.objects_tbl[1].data.p.current_anim_num = 8;
g_vars.level_current_bonus_x_pos = g_vars.objects_tbl[1].x_pos;
g_vars.level_current_bonus_y_pos = g_vars.objects_tbl[1].y_pos - 48;
g_vars.current_bonus.x_pos = g_vars.objects_tbl[1].x_pos;
g_vars.current_bonus.y_pos = g_vars.objects_tbl[1].y_pos - 48;
const int count = g_vars.player_energy * 6 + g_vars.bonus_energy_counter;
if (count != 0) {
g_vars.player_energy = 0;
g_vars.bonus_energy_counter = 0;
g_vars.level_current_bonus_spr_num = 0x2046;
g_vars.current_bonus.spr_num = 0x2046;
level_add_object23_bonus(48, -128, count);
}
g_vars.player_platform_counter = 7;
g_vars.shake_screen_counter = 7;
level_clear_item(obj);
level_add_object75_score(obj, 228);
} else if (num == 173) {
@ -2288,10 +2301,46 @@ static void level_update_player_collision() {
}
} else if (num == 169) {
play_sound(0);
for (int i = 0; i < 12; ++i) {
struct object_t *obj = &g_vars.objects_tbl[11 + i];
if (obj->spr_num == 0xFFFF) {
continue;
}
if ((obj->spr_num & 0x2000) == 0) {
continue;
}
print_warning("Unhandled bonus num 169");
}
g_vars.shake_screen_counter = 9;
level_clear_item(obj);
level_add_object75_score(obj, 230);
} else if (num == 170) { /* bomb */
play_sound(0);
print_warning("Unhandled bonus num 170");
for (int i = 0; i < 12; ++i) {
struct object_t *obj = &g_vars.objects_tbl[11 + i];
if (obj->spr_num == 0xFFFF) {
continue;
}
if ((obj->spr_num & 0x2000) == 0) {
continue;
}
g_vars.current_bonus.x_pos = obj->x_pos;
g_vars.current_bonus.y_pos = obj->y_pos;
obj->data.m.unkE = 0xFF;
obj->spr_num = 0xFFFF;
int x_vel = 32;
int y_vel = -160;
for (int i = 0; i < 4; ++i) {
g_vars.current_bonus.spr_num = level_get_random_bonus_spr_num();
level_add_object23_bonus(x_vel, y_vel, 4);
x_vel = -x_vel;
if (x_vel >= 0) {
x_vel -= 16;
y_vel -= 16;
}
}
}
level_clear_item(obj);
} else if (num == 181) { /* light off */
if (g_vars.light.state != 1) {
play_sound(1);
@ -2303,8 +2352,8 @@ static void level_update_player_collision() {
level_clear_item(obj);
} else if (num == 180) { /* light on */
if (g_vars.light.state != 0) {
g_vars.light.palette_flag2 = 0;
g_vars.light.palette_flag1 = 1;
g_vars.light.palette_flag1 = 0;
g_vars.light.palette_flag2 = 1;
g_vars.light.palette_counter = 0;
g_vars.light.state = 0;
}
@ -2607,8 +2656,10 @@ static void level_draw_objects() {
}
const int spr_num = obj->spr_num & 0x1FFF;
const int spr_hflip = ((obj->spr_num & 0x8000) != 0) ? 1 : 0;
const int spr_y_pos = obj->y_pos - ((g_vars.tilemap_y << 4) + g_vars.tilemap_scroll_dy) - spr_size_tbl[2 * spr_num + 1];
int spr_x_pos = obj->x_pos - ((g_vars.tilemap_x << 4) + (g_vars.tilemap_scroll_dx << 2));
int spr_y_pos = obj->y_pos - ((g_vars.tilemap_y << 4) + g_vars.tilemap_scroll_dy);
int spr_h = spr_size_tbl[2 * spr_num + 1];
spr_y_pos -= spr_h;
int spr_x_pos = obj->x_pos - ((g_vars.tilemap_x << 4) + g_vars.tilemap_scroll_dx);
int spr_w = spr_offs_tbl[2 * spr_num];
if (spr_hflip) {
spr_w = spr_size_tbl[2 * spr_num] - spr_w;
@ -2659,9 +2710,9 @@ static void level_draw_snow() {
static void level_update_player_bonuses() {
if (g_vars.player_bonus_letters_mask == 0x1F) { /* found the 5 bonuses */
g_vars.level_current_bonus_x_pos = g_vars.objects_tbl[1].x_pos;
g_vars.level_current_bonus_y_pos = g_vars.objects_tbl[1].y_pos - 112;
g_vars.level_current_bonus_spr_num = 110;
g_vars.current_bonus.x_pos = g_vars.objects_tbl[1].x_pos;
g_vars.current_bonus.y_pos = g_vars.objects_tbl[1].y_pos - 112;
g_vars.current_bonus.spr_num = 110;
level_add_object23_bonus(0, 0, 1);
g_vars.player_bonus_letters_mask = 0;
g_vars.player_bonus_letters_blinking_counter = 44; /* blink the letters in the panel */
@ -2671,16 +2722,19 @@ static void level_update_player_bonuses() {
}
}
static void level_fixup_player_y_pos() {
if (g_vars.player_platform_counter < 1) {
static void level_shake_screen() {
if (g_vars.shake_screen_counter < 1) {
return;
} else if (g_vars.player_platform_counter == 1) {
} else if (g_vars.shake_screen_counter == 1) {
g_vars.shake_screen_voffset = 0;
} else if ((g_vars.level_draw_counter & 1) == 0) {
g_vars.shake_screen_voffset = 0;
} else {
if (g_vars.objects_tbl[1].data.p.current_anim_num != 5 && g_vars.objects_tbl[1].data.p.current_anim_num != 32) {
g_vars.objects_tbl[1].y_pos -= 12;
}
++g_vars.player_platform_counter;
++g_vars.shake_screen_counter;
g_vars.shake_screen_voffset = g_vars.shake_screen_counter;
}
}
@ -2964,6 +3018,6 @@ void do_level() {
level_sync();
level_update_light_palette();
level_update_player_bonuses();
level_fixup_player_y_pos();
level_shake_screen();
}
}

View File

@ -3,6 +3,8 @@
#include "unpack.h"
#include "util.h"
static const bool _dump_data = true;
static const int BACKGROUND_SIZE = 320 * 200;
static const char *_datapath;
@ -112,6 +114,16 @@ void load_leveldat(const uint8_t *p, struct level_t *level) {
platform->unk9 = *p++;
}
memcpy(g_res.level.monsters_attributes, p, 0x800); p += 0x800;
if (_dump_data) {
const uint8_t *p = g_res.level.monsters_attributes;
for (int i = 0; *p < 50; ++i) {
const uint8_t len = p[0];
const uint8_t type = p[1] & 0x7F;
const uint16_t spr_num = READ_LE_UINT16(p + 2);
print_debug(DBG_RESOURCE, "monster %d len %d type %d spr %d", i, len, type, spr_num);
p += len;
}
}
g_res.level.items_spr_num_offset = READ_LE_UINT16(p); p += 2;
g_res.level.monsters_spr_num_offset = READ_LE_UINT16(p); p += 2;
for (int i = 0; i < MAX_LEVEL_BONUSES; ++i) {
@ -135,12 +147,20 @@ void load_leveldat(const uint8_t *p, struct level_t *level) {
trigger->y_pos = READ_LE_UINT16(p); p += 2;
trigger->spr_num = READ_LE_UINT16(p); p += 2;
trigger->flags = *p++;
trigger->unk7 = *p++;
trigger->unk8 = *p++;
trigger->unk9 = *p++;
trigger->state = *p++;
trigger->unkB = READ_LE_UINT16(p); p += 2;
trigger->counter = *p++;
const int type = trigger->flags & 15;
if (type == 8) {
trigger->type8.unk7 = *p++;
trigger->type8.unk8 = *p++;
trigger->type8.unk9 = *p++;
trigger->type8.state = *p++;
trigger->type8.y_delta = READ_LE_UINT16(p); p += 2;
trigger->type8.counter = *p++;
} else {
trigger->other.unk7 = READ_LE_UINT16(p); p += 2;
trigger->other.unk9 = *p++;
trigger->other.unkA = READ_LE_UINT16(p); p += 2;
trigger->other.unkC = READ_LE_UINT16(p); p += 2;
}
trigger->unkE = *p++;
}
g_res.level.monsters_xmin = READ_LE_UINT16(p); p += 2;

View File

@ -39,12 +39,22 @@ struct level_trigger_t {
uint16_t y_pos;
uint16_t spr_num;
uint8_t flags;
uint8_t unk7;
union {
struct {
int8_t unk7;
uint8_t unk8;
uint8_t unk9;
uint8_t state;
uint16_t unkB;
uint8_t counter;
uint8_t state; // 0xA
uint16_t y_delta; // 0xB
uint8_t counter; // 0xD
} type8;
struct {
int16_t unk7;
uint8_t unk9;
int16_t unkA;
int16_t unkC;
} other;
};
uint8_t unkE;
}; // sizeof == 15

View File

@ -98,6 +98,17 @@ void video_draw_panel(const uint8_t *src) {
void video_draw_tile(const uint8_t *src, int x_offset, int y_offset) {
int tile_w = 16;
if (x_offset < 0) {
tile_w += x_offset;
src -= x_offset / 2;
x_offset = 0;
}
if (x_offset + tile_w > TILEMAP_SCREEN_W) {
tile_w = TILEMAP_SCREEN_W - x_offset;
}
if (tile_w <= 0) {
return;
}
int tile_h = 16;
if (y_offset < 0) {
tile_h += y_offset;
@ -113,7 +124,7 @@ void video_draw_tile(const uint8_t *src, int x_offset, int y_offset) {
uint8_t *dst = g_res.vga + y_offset * TILEMAP_SCREEN_W + x_offset;
for (int y = 0; y < tile_h; ++y) {
for (int x = 0; x < tile_w / 2; ++x) {
const uint8_t color = *src++;
const uint8_t color = src[x];
const uint8_t c1 = color >> 4;
if (c1 != 0) {
dst[x * 2] = c1;
@ -123,6 +134,7 @@ void video_draw_tile(const uint8_t *src, int x_offset, int y_offset) {
dst[x * 2 + 1] = c2;
}
}
src += 8;
dst += TILEMAP_SCREEN_W;
}
}

View File

@ -475,10 +475,19 @@ static void handle_joystickbutton(int button, int pressed) {
}
}
static int handle_event(const SDL_Event *ev) {
static int handle_event(const SDL_Event *ev, bool *paused) {
switch (ev->type) {
case SDL_QUIT:
_input->quit = 1;
_input->quit = true;
break;
case SDL_WINDOWEVENT:
switch (ev->window.event) {
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);
@ -543,13 +552,20 @@ static int handle_event(const SDL_Event *ev) {
}
static void sdl2_process_events() {
bool paused = false;
while (1) {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
handle_event(&ev);
handle_event(&ev, &paused);
if (_input->quit) {
break;
}
}
if (!paused) {
break;
}
SDL_Delay(100);
}
}
static void sdl2_sleep(int duration) {