Import blues from abd80e9b
This commit is contained in:
parent
ef58debe84
commit
ec71a464eb
6
decode.c
6
decode.c
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
#include "decode.h"
|
#include "decode.h"
|
||||||
|
|
||||||
void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, int xflip) {
|
void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *dst, int dst_pitch, int dst_x, int dst_y) {
|
||||||
assert((src_pitch & 7) == 0);
|
assert((src_pitch & 7) == 0);
|
||||||
src_pitch /= 8;
|
src_pitch /= 8;
|
||||||
assert((w & 7) == 0);
|
assert((w & 7) == 0);
|
||||||
|
@ -19,12 +19,10 @@ void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *ds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (color != 0) {
|
if (color != 0) {
|
||||||
const int x_offset = dst_x + (xflip ? (w * 8 - x * 8 - i) : (x * 8 + i));
|
const int x_offset = dst_x + (x * 8 + i);
|
||||||
if (x_offset >= 0 && x_offset < 320 && y_offset >= 0 && y_offset < 200) {
|
|
||||||
dst[y_offset * dst_pitch + x_offset] = color;
|
dst[y_offset * dst_pitch + x_offset] = color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
++src;
|
++src;
|
||||||
}
|
}
|
||||||
src += src_pitch - w;
|
src += src_pitch - w;
|
||||||
|
|
2
decode.h
2
decode.h
|
@ -4,6 +4,6 @@
|
||||||
|
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
|
|
||||||
extern void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *dst, int dst_pitch, int dst_x, int dst_y, int xflip);
|
extern void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *dst, int dst_pitch, int dst_x, int dst_y);
|
||||||
|
|
||||||
#endif /* DECODE_H__ */
|
#endif /* DECODE_H__ */
|
||||||
|
|
23
game.c
23
game.c
|
@ -47,13 +47,14 @@ static void check_cheat_code() {
|
||||||
|
|
||||||
void do_select_player() {
|
void do_select_player() {
|
||||||
int quit = 0;
|
int quit = 0;
|
||||||
int var9 = 0;
|
int fade = 0;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
int frame1 = 1;
|
int frame1 = 1;
|
||||||
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("choix.sqz");
|
load_img("choix.sqz");
|
||||||
|
screen_load_graphics();
|
||||||
screen_clear_sprites();
|
screen_clear_sprites();
|
||||||
do {
|
do {
|
||||||
screen_unk4();
|
screen_unk4();
|
||||||
|
@ -174,9 +175,9 @@ void do_select_player() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// state_default_:
|
// state_default_:
|
||||||
if (var9 == 0) {
|
if (!fade) {
|
||||||
fade_in_palette();
|
fade_in_palette();
|
||||||
var9 = 1;
|
fade = 1;
|
||||||
for (int i = 0; i < colors_count; ++i) {
|
for (int i = 0; i < colors_count; ++i) {
|
||||||
screen_adjust_palette_color( 3, color_rgb, 1);
|
screen_adjust_palette_color( 3, color_rgb, 1);
|
||||||
screen_adjust_palette_color(10, color_rgb, 1);
|
screen_adjust_palette_color(10, color_rgb, 1);
|
||||||
|
@ -208,16 +209,12 @@ void do_select_player() {
|
||||||
} while (!quit && !g_sys.input.quit);
|
} while (!quit && !g_sys.input.quit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_inter_screen_helper(int a, int b, int c) {
|
static void do_inter_screen_helper(int xpos, int ypos, int c) {
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
g_vars.screen_draw_offset ^= 0x2000;
|
g_vars.screen_draw_offset ^= 0x2000;
|
||||||
}
|
}
|
||||||
int xpos = a + 20;
|
|
||||||
int ypos = b - 20;
|
|
||||||
for (int i = 0; i < 40; ++i) {
|
for (int i = 0; i < 40; ++i) {
|
||||||
--xpos;
|
screen_add_sprite(xpos + 20 - 1 - i, ypos - 20 + 1 + i, 125);
|
||||||
++ypos;
|
|
||||||
screen_add_sprite(xpos, ypos, 125);
|
|
||||||
screen_clear_last_sprite();
|
screen_clear_last_sprite();
|
||||||
screen_redraw_sprites();
|
screen_redraw_sprites();
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
|
@ -226,9 +223,7 @@ static void do_inter_screen_helper(int a, int b, int c) {
|
||||||
screen_clear_sprites();
|
screen_clear_sprites();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 40; ++i) {
|
for (int i = 0; i < 40; ++i) {
|
||||||
++xpos;
|
screen_add_sprite(xpos - 20 + 1 + i, ypos - 20 + 1 + i, 125);
|
||||||
++ypos;
|
|
||||||
screen_add_sprite(xpos, ypos, 125);
|
|
||||||
screen_clear_last_sprite();
|
screen_clear_last_sprite();
|
||||||
screen_redraw_sprites();
|
screen_redraw_sprites();
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
|
@ -288,7 +283,7 @@ void game_main() {
|
||||||
screen_flip();
|
screen_flip();
|
||||||
screen_init();
|
screen_init();
|
||||||
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, "Blues Brothers");
|
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, "Blues Brothers");
|
||||||
g_vars.start_level = g_options.start_level;
|
g_vars.start_level = 0;
|
||||||
load_sqv("sprite.sqv", g_res.spr_sqv, 0);
|
load_sqv("sprite.sqv", g_res.spr_sqv, 0);
|
||||||
do_title_screen();
|
do_title_screen();
|
||||||
while (g_sys.input.quit == 0) {
|
while (g_sys.input.quit == 0) {
|
||||||
|
@ -297,7 +292,7 @@ void game_main() {
|
||||||
g_vars.game_over_flag = 0;
|
g_vars.game_over_flag = 0;
|
||||||
g_vars.play_level_flag = 1;
|
g_vars.play_level_flag = 1;
|
||||||
if (!g_vars.play_demo_flag) {
|
if (!g_vars.play_demo_flag) {
|
||||||
g_vars.level = 0;
|
g_vars.level = g_options.start_level;
|
||||||
do_select_player();
|
do_select_player();
|
||||||
} else {
|
} else {
|
||||||
g_vars.level = g_vars.start_level;
|
g_vars.level = g_vars.start_level;
|
||||||
|
|
21
game.h
21
game.h
|
@ -17,7 +17,6 @@
|
||||||
#define MAX_DOORS 30
|
#define MAX_DOORS 30
|
||||||
#define MAX_LEVELS 6
|
#define MAX_LEVELS 6
|
||||||
#define MAX_OBJECTS 41
|
#define MAX_OBJECTS 41
|
||||||
#define MAX_SPRITES 40
|
|
||||||
|
|
||||||
#define SOUND_0 0
|
#define SOUND_0 0
|
||||||
#define SOUND_2 2
|
#define SOUND_2 2
|
||||||
|
@ -47,17 +46,6 @@ struct options_t {
|
||||||
|
|
||||||
extern struct options_t g_options;
|
extern struct options_t g_options;
|
||||||
|
|
||||||
struct sprite_t {
|
|
||||||
int16_t xpos;
|
|
||||||
int16_t ypos;
|
|
||||||
int16_t spr_w;
|
|
||||||
int16_t spr_h;
|
|
||||||
const uint8_t *frame;
|
|
||||||
struct sprite_t *next_sprite;
|
|
||||||
int16_t xflip;
|
|
||||||
int16_t unk16;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct door_t {
|
struct door_t {
|
||||||
uint16_t src_x16, src_y16;
|
uint16_t src_x16, src_y16;
|
||||||
uint16_t dst_x16, dst_y16;
|
uint16_t dst_x16, dst_y16;
|
||||||
|
@ -96,7 +84,7 @@ struct object_t {
|
||||||
int16_t unk1C; // xvelocity / 8
|
int16_t unk1C; // xvelocity / 8
|
||||||
int16_t unk1E; // yvelocity / 8
|
int16_t unk1E; // yvelocity / 8
|
||||||
uint8_t direction_lr;
|
uint8_t direction_lr;
|
||||||
uint8_t direction_ud;
|
int8_t direction_ud;
|
||||||
int16_t xpos16; // tilemap_xpos
|
int16_t xpos16; // tilemap_xpos
|
||||||
int16_t ypos16; // tilemap_ypos
|
int16_t ypos16; // tilemap_ypos
|
||||||
// int16_t unk26;
|
// int16_t unk26;
|
||||||
|
@ -194,9 +182,6 @@ struct vars_t {
|
||||||
uint16_t level_loop_counter;
|
uint16_t level_loop_counter;
|
||||||
int triggers_counter;
|
int triggers_counter;
|
||||||
int update_objects_counter;
|
int update_objects_counter;
|
||||||
struct sprite_t sprites_table[MAX_SPRITES];
|
|
||||||
struct sprite_t *sprites[MAX_SPRITES];
|
|
||||||
int sprites_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct vars_t g_vars;
|
extern struct vars_t g_vars;
|
||||||
|
@ -243,7 +228,7 @@ extern void do_level_update_panel_lifes(struct object_t *);
|
||||||
extern void do_level_enter_door(struct object_t *);
|
extern void do_level_enter_door(struct object_t *);
|
||||||
extern void do_level_player_hit(struct object_t *);
|
extern void do_level_player_hit(struct object_t *);
|
||||||
extern void do_level_drop_grabbed_object(struct object_t *);
|
extern void do_level_drop_grabbed_object(struct object_t *);
|
||||||
extern void do_level_update_object38(struct object_t *obj);
|
extern void do_level_update_projectile(struct object_t *obj);
|
||||||
extern void do_level();
|
extern void do_level();
|
||||||
|
|
||||||
/* opcodes.c */
|
/* opcodes.c */
|
||||||
|
@ -259,7 +244,6 @@ extern void fade_in_palette();
|
||||||
extern void fade_out_palette();
|
extern void fade_out_palette();
|
||||||
extern void screen_adjust_palette_color(int color, int b, int c);
|
extern void screen_adjust_palette_color(int color, int b, int c);
|
||||||
extern void screen_vsync();
|
extern void screen_vsync();
|
||||||
extern void screen_set_palette();
|
|
||||||
extern void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d);
|
extern void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d);
|
||||||
extern void screen_flip();
|
extern void screen_flip();
|
||||||
extern void screen_unk4();
|
extern void screen_unk4();
|
||||||
|
@ -276,6 +260,7 @@ 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);
|
||||||
extern void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter);
|
extern void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter);
|
||||||
extern void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter);
|
extern void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter);
|
||||||
|
extern void screen_load_graphics();
|
||||||
|
|
||||||
/* sound.c */
|
/* sound.c */
|
||||||
extern void sound_init(int rate);
|
extern void sound_init(int rate);
|
||||||
|
|
96
level.c
96
level.c
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
/* level main loop */
|
/* level main loop */
|
||||||
|
|
||||||
#include "decode.h"
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
@ -66,13 +65,14 @@ void load_level_data(int num) {
|
||||||
}
|
}
|
||||||
load_bin(_levels[num].bin);
|
load_bin(_levels[num].bin);
|
||||||
load_avt(_levels[num].avt, g_res.avt_sqv, 0);
|
load_avt(_levels[num].avt, g_res.avt_sqv, 0);
|
||||||
load_sqv(_levels[num].sqv, g_res.tmp, 146);
|
load_sqv(_levels[num].sqv, g_res.tmp, SPRITES_COUNT);
|
||||||
memcpy(g_vars.level_xpos, _levels[num].xpos, MAX_OBJECTS * sizeof(int16_t));
|
memcpy(g_vars.level_xpos, _levels[num].xpos, MAX_OBJECTS * sizeof(int16_t));
|
||||||
memcpy(g_vars.level_ypos, _levels[num].ypos, MAX_OBJECTS * sizeof(int16_t));
|
memcpy(g_vars.level_ypos, _levels[num].ypos, MAX_OBJECTS * sizeof(int16_t));
|
||||||
if (g_vars.music_num != _levels[num].music) {
|
if (g_vars.music_num != _levels[num].music) {
|
||||||
play_music(_levels[num].music);
|
play_music(_levels[num].music);
|
||||||
g_vars.music_num = _levels[num].music;
|
g_vars.music_num = _levels[num].music;
|
||||||
}
|
}
|
||||||
|
screen_load_graphics();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_level() {
|
static void init_level() {
|
||||||
|
@ -502,6 +502,64 @@ static void do_level_add_sprite1_case2(struct object_t *obj) {
|
||||||
obj->anim_frame = anim_data[obj->anim_num];
|
obj->anim_frame = anim_data[obj->anim_num];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_level_add_sprite1_case3(struct object_t *obj) {
|
||||||
|
struct object_t *obj35 = &g_vars.objects[35];
|
||||||
|
struct object_t *obj37 = &g_vars.objects[37];
|
||||||
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
||||||
|
obj35 = &g_vars.objects[34];
|
||||||
|
obj37 = &g_vars.objects[36];
|
||||||
|
}
|
||||||
|
if (obj37->type != 100 && obj37->grab_type != 0) {
|
||||||
|
do_level_drop_grabbed_object(obj);
|
||||||
|
}
|
||||||
|
obj->unk3D = 0;
|
||||||
|
if (obj35->type != 100) {
|
||||||
|
obj35->type = 100;
|
||||||
|
obj35->visible_flag = 0;
|
||||||
|
}
|
||||||
|
const uint8_t *anim_data = 0;
|
||||||
|
obj->unk3D = 0;
|
||||||
|
int tile_num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
||||||
|
obj->xmaxvelocity = 8;
|
||||||
|
obj->xacc = 0;
|
||||||
|
obj->unk2D = 10;
|
||||||
|
if (obj->direction_lr != 0) {
|
||||||
|
if (obj->direction_ud != 0) {
|
||||||
|
if (tile_num == 6) {
|
||||||
|
anim_data = obj->animframes_ptr[56 / 4];
|
||||||
|
} else {
|
||||||
|
anim_data = obj->animframes_ptr[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tile_num == 6) {
|
||||||
|
anim_data = obj->animframes_ptr[68 / 4];
|
||||||
|
} else {
|
||||||
|
anim_data = obj->animframes_ptr[4 / 4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (obj->direction_ud != 0) {
|
||||||
|
if (tile_num == 6) {
|
||||||
|
anim_data = obj->animframes_ptr[56 / 4];
|
||||||
|
} else {
|
||||||
|
anim_data = obj->animframes_ptr[0];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tile_num == 6) {
|
||||||
|
anim_data = obj->animframes_ptr[68 / 4];
|
||||||
|
} else {
|
||||||
|
anim_data = obj->animframes_ptr[4 / 4];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj->anim_num < anim_data[0]) {
|
||||||
|
obj->anim_num += (g_vars.level_loop_counter & 1);
|
||||||
|
} else {
|
||||||
|
obj->anim_num = 1;
|
||||||
|
}
|
||||||
|
obj->anim_frame = anim_data[obj->anim_num];
|
||||||
|
}
|
||||||
|
|
||||||
// swimming
|
// swimming
|
||||||
static void do_level_add_sprite1_case4(struct object_t *obj) {
|
static void do_level_add_sprite1_case4(struct object_t *obj) {
|
||||||
struct object_t *obj35 = &g_vars.objects[35];
|
struct object_t *obj35 = &g_vars.objects[35];
|
||||||
|
@ -608,6 +666,9 @@ static void do_level_add_sprite1(struct object_t *obj) {
|
||||||
case 2:
|
case 2:
|
||||||
do_level_add_sprite1_case2(obj);
|
do_level_add_sprite1_case2(obj);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
do_level_add_sprite1_case3(obj);
|
||||||
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
do_level_add_sprite1_case4(obj);
|
do_level_add_sprite1_case4(obj);
|
||||||
break;
|
break;
|
||||||
|
@ -1335,17 +1396,17 @@ static void do_level_update_object_bounds(struct object_t *obj) {
|
||||||
// obj->unk41 = 0;
|
// obj->unk41 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_level_update_object38(struct object_t *obj) {
|
void do_level_update_projectile(struct object_t *obj) {
|
||||||
struct object_t *obj38 = &g_vars.objects[38];
|
struct object_t *obj38 = &g_vars.objects[38];
|
||||||
if (obj->unk42 == 0) {
|
if (obj->unk42 == 0) {
|
||||||
if (obj->type == 100) {
|
if (obj38->type == 100) {
|
||||||
obj->special_anim = 2;
|
obj->special_anim = 2;
|
||||||
obj->unk42 = 1;
|
obj->unk42 = 1;
|
||||||
}
|
}
|
||||||
} else if (obj->unk42 == 1) {
|
} else if (obj->unk42 == 1) {
|
||||||
if (obj38->grab_type == 10 || obj->anim_num >= 7) {
|
if (obj38->grab_type == 10 || obj->anim_num >= 7) {
|
||||||
obj38->type = 2;
|
obj38->type = 2;
|
||||||
obj->visible_flag = 1;
|
obj38->visible_flag = 1;
|
||||||
static const uint8_t data[MAX_OBJECTS] = {
|
static const uint8_t data[MAX_OBJECTS] = {
|
||||||
0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 23, 0, 9, 9, 0, 10, 0,
|
0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 23, 0, 9, 9, 0, 10, 0,
|
||||||
11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0
|
11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0
|
||||||
|
@ -1375,6 +1436,11 @@ void do_level_update_object38(struct object_t *obj) {
|
||||||
obj38->xpos = obj->xpos + 16 - (obj->facing_left << 5);
|
obj38->xpos = obj->xpos + 16 - (obj->facing_left << 5);
|
||||||
obj38->xvelocity = obj38->yvelocity = 32 - (obj->facing_left << 6);
|
obj38->xvelocity = obj38->yvelocity = 32 - (obj->facing_left << 6);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
obj38->ypos = obj->ypos - 18;
|
||||||
|
obj38->xpos = obj->xpos + 32 - (obj->facing_left << 6);
|
||||||
|
obj38->xvelocity = obj38->yvelocity = 64 - (obj->facing_left << 7);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
const int num = obj38->type * 116 / 4;
|
const int num = obj38->type * 116 / 4;
|
||||||
assert(num < 1189);
|
assert(num < 1189);
|
||||||
|
@ -1842,7 +1908,17 @@ static void do_level_update_objects() {
|
||||||
obj->direction_lr = 0;
|
obj->direction_lr = 0;
|
||||||
obj->direction_ud = 0;
|
obj->direction_ud = 0;
|
||||||
if (obj->type < 2) {
|
if (obj->type < 2) {
|
||||||
if (g_vars.inp_keyboard[0xC1] != 0) { // F7
|
if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player
|
||||||
|
if (!g_vars.screen_unk1 && g_vars.two_players_flag) {
|
||||||
|
if (!g_vars.player2_scrolling_flag && g_vars.objects[OBJECT_NUM_PLAYER1].unk53 == 0) {
|
||||||
|
g_vars.player2_scrolling_flag = 1;
|
||||||
|
g_vars.screen_unk1 = 1;
|
||||||
|
} else if (g_vars.player2_scrolling_flag && g_vars.objects[OBJECT_NUM_PLAYER2].unk53 == 0) {
|
||||||
|
g_vars.player2_scrolling_flag = 1;
|
||||||
|
g_vars.screen_unk1 = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_vars.inp_keyboard[0xC1] = 0;
|
||||||
}
|
}
|
||||||
if (obj->blinking_counter != 0) {
|
if (obj->blinking_counter != 0) {
|
||||||
--obj->blinking_counter;
|
--obj->blinking_counter;
|
||||||
|
@ -1896,7 +1972,7 @@ static void do_level_update_objects() {
|
||||||
if (obj->visible_flag != 0) {
|
if (obj->visible_flag != 0) {
|
||||||
do_level_update_object_bounds(obj);
|
do_level_update_object_bounds(obj);
|
||||||
if (obj->unk42 != 0) {
|
if (obj->unk42 != 0) {
|
||||||
do_level_update_object38(obj);
|
do_level_update_projectile(obj);
|
||||||
}
|
}
|
||||||
obj->unk2D = 10;
|
obj->unk2D = 10;
|
||||||
obj->unk1C = 0;
|
obj->unk1C = 0;
|
||||||
|
@ -2046,9 +2122,9 @@ 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 + 14;
|
const int tile_y = j * 16 + TILEMAP_OFFSET_Y;
|
||||||
const int tile_x = i * 16;
|
const int tile_x = i * 16;
|
||||||
decode_ega_spr(g_res.avt[avt_num], 16, 16, 16, g_res.vga, GAME_SCREEN_W, tile_x, tile_y, 0);
|
render_add_sprite(RENDER_SPR_FG, avt_num, tile_x, tile_y, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++y;
|
++y;
|
||||||
|
@ -2098,7 +2174,7 @@ void do_level() {
|
||||||
do {
|
do {
|
||||||
const uint32_t timestamp = g_sys.get_timestamp();
|
const uint32_t timestamp = g_sys.get_timestamp();
|
||||||
update_input();
|
update_input();
|
||||||
if (g_vars.inp_keyboard[0xBF] != 0) { // F5
|
if (g_vars.inp_keyboard[0xBF] != 0) { // F5, quit game
|
||||||
play_sound(SOUND_0);
|
play_sound(SOUND_0);
|
||||||
g_vars.inp_keyboard[0xBF] = 0;
|
g_vars.inp_keyboard[0xBF] = 0;
|
||||||
g_vars.quit_level_flag = 1;
|
g_vars.quit_level_flag = 1;
|
||||||
|
|
52
opcodes.c
52
opcodes.c
|
@ -49,18 +49,18 @@ static void object_func_op2(struct object_t *obj) {
|
||||||
obj->moving_direction ^= 1;
|
obj->moving_direction ^= 1;
|
||||||
}
|
}
|
||||||
obj->direction_lr = obj->moving_direction + 1;
|
obj->direction_lr = obj->moving_direction + 1;
|
||||||
obj->xmaxvelocity = 40;
|
obj->xmaxvelocity = 24;
|
||||||
if (obj->anim_num == 12 && obj->special_anim == 2) {
|
if (obj->anim_num == 12 && obj->special_anim == 2) {
|
||||||
obj->special_anim = 3;
|
obj->special_anim = 3;
|
||||||
obj->anim_num = 1;
|
obj->anim_num = 1;
|
||||||
} else if (obj->anim_num == 12 && obj->special_anim == 3) {
|
} else if (obj->anim_num == 12 && obj->special_anim == 3) {
|
||||||
obj->special_anim = 0;
|
obj->special_anim = 0;
|
||||||
}
|
}
|
||||||
if (obj->player_ydist <= 0 && obj->player_xdist > -(TILEMAP_SCREEN_W / 4) && obj->player_xdist < (TILEMAP_SCREEN_W / 4) && obj->direction_ud > 196) {
|
if (obj->player_ydist <= 20 && obj->player_xdist > -(TILEMAP_SCREEN_W / 4) && obj->player_xdist < (TILEMAP_SCREEN_W / 4) && obj->direction_ud > -60) {
|
||||||
if (obj->special_anim == 0 || obj->anim_num == 12) {
|
if (obj->special_anim == 0 || obj->anim_num == 12) {
|
||||||
obj->anim_num = 1;
|
obj->anim_num = 1;
|
||||||
obj->unk42 = 0;
|
obj->unk42 = 0;
|
||||||
do_level_update_object38(obj);
|
do_level_update_projectile(obj);
|
||||||
}
|
}
|
||||||
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,9 @@ static void object_func_op2(struct object_t *obj) {
|
||||||
|
|
||||||
static void object_func_op3(struct object_t *obj) {
|
static void object_func_op3(struct object_t *obj) {
|
||||||
if (obj->player_ydist <= 20 && obj->player_ydist > -(TILEMAP_SCREEN_W / 2) && obj->player_xdist < (TILEMAP_SCREEN_W / 2) && g_vars.objects[38].type == 100) {
|
if (obj->player_ydist <= 20 && obj->player_ydist > -(TILEMAP_SCREEN_W / 2) && obj->player_xdist < (TILEMAP_SCREEN_W / 2) && g_vars.objects[38].type == 100) {
|
||||||
if (obj->direction_ud > 226) {
|
if (obj->direction_ud > -30) {
|
||||||
if (obj->special_anim == 0 || obj->anim_num == 16) {
|
if (obj->special_anim == 0 || obj->anim_num == 16) {
|
||||||
do_level_update_object38(obj);
|
do_level_update_projectile(obj);
|
||||||
}
|
}
|
||||||
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,37 @@ static void object_func_op5(struct object_t *obj) {
|
||||||
obj->xmaxvelocity = 32;
|
obj->xmaxvelocity = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void object_func_op7(struct object_t *obj) {
|
||||||
|
if (triggers_get_tile_type(obj->xpos16 + 2 - obj->facing_left * 4, obj->ypos16) == 12) {
|
||||||
|
obj->moving_direction ^= 1;
|
||||||
|
}
|
||||||
|
obj->direction_lr = obj->moving_direction + 1;
|
||||||
|
obj->xmaxvelocity = 32;
|
||||||
|
if (g_vars.objects[OBJECT_NUM_PLAYER1].special_anim != 18 && g_vars.objects[OBJECT_NUM_PLAYER2].special_anim != 18) {
|
||||||
|
if (obj->player_ydist <= 10 && obj->player_xdist > -(TILEMAP_SCREEN_W / 4) && obj->player_xdist < (TILEMAP_SCREEN_W / 4) && g_vars.objects[38].type == 100) {
|
||||||
|
if (obj->direction_ud > -30) {
|
||||||
|
if (obj->special_anim == 0 || obj->anim_num == 16) {
|
||||||
|
obj->anim_num = 1;
|
||||||
|
obj->unk42 = 0;
|
||||||
|
do_level_update_projectile(obj);
|
||||||
|
}
|
||||||
|
if (obj->player_xdist < 0) {
|
||||||
|
obj->facing_left = 1;
|
||||||
|
} else {
|
||||||
|
obj->facing_left = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (obj->anim_num == 16) {
|
||||||
|
obj->special_anim = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj->special_anim != 0) {
|
||||||
|
obj->direction_lr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// bird
|
// bird
|
||||||
static void object_func_op8(struct object_t *obj) {
|
static void object_func_op8(struct object_t *obj) {
|
||||||
if (triggers_get_tile_type(obj->xpos16 + 2 - obj->facing_left * 4, obj->ypos16) != 1) {
|
if (triggers_get_tile_type(obj->xpos16 + 2 - obj->facing_left * 4, obj->ypos16) != 1) {
|
||||||
|
@ -163,10 +194,10 @@ static void object_func_op8(struct object_t *obj) {
|
||||||
obj->xmaxvelocity = 48;
|
obj->xmaxvelocity = 48;
|
||||||
obj->yacc = 0;
|
obj->yacc = 0;
|
||||||
obj->yvelocity = 0;
|
obj->yvelocity = 0;
|
||||||
if (obj->player_ydist <= 100 && obj->player_xdist > -90 && obj->player_xdist < 90 && obj->direction_ud > 196 && obj->special_anim == 0) {
|
if (obj->player_ydist <= 100 && obj->player_xdist > -90 && obj->player_xdist < 90 && obj->direction_ud > -60 && obj->special_anim == 0) {
|
||||||
obj->anim_num = 1;
|
obj->anim_num = 1;
|
||||||
obj->unk42 = 1;
|
obj->unk42 = 1;
|
||||||
do_level_update_object38(obj);
|
do_level_update_projectile(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -177,11 +208,11 @@ static void object_func_op10(struct object_t *obj) {
|
||||||
obj->direction_lr = obj->moving_direction + 1;
|
obj->direction_lr = obj->moving_direction + 1;
|
||||||
obj->xmaxvelocity = 32;
|
obj->xmaxvelocity = 32;
|
||||||
if (obj->player_ydist <= 10 && obj->player_xdist > -(TILEMAP_SCREEN_W / 2) && obj->player_xdist < (TILEMAP_SCREEN_W / 2) && g_vars.objects[38].type == 100) {
|
if (obj->player_ydist <= 10 && obj->player_xdist > -(TILEMAP_SCREEN_W / 2) && obj->player_xdist < (TILEMAP_SCREEN_W / 2) && g_vars.objects[38].type == 100) {
|
||||||
if (obj->direction_ud > 226) {
|
if (obj->direction_ud > -30) {
|
||||||
if (obj->special_anim == 0 || obj->anim_num == 16) {
|
if (obj->special_anim == 0 || obj->anim_num == 16) {
|
||||||
obj->anim_num = 1;
|
obj->anim_num = 1;
|
||||||
obj->unk42 = 0;
|
obj->unk42 = 0;
|
||||||
do_level_update_object38(obj);
|
do_level_update_projectile(obj);
|
||||||
}
|
}
|
||||||
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
obj->facing_left = (obj->player_xdist < 0) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -436,6 +467,9 @@ void level_call_object_func(struct object_t *obj) {
|
||||||
case 5:
|
case 5:
|
||||||
object_func_op5(obj);
|
object_func_op5(obj);
|
||||||
break;
|
break;
|
||||||
|
case 7:
|
||||||
|
object_func_op7(obj);
|
||||||
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
object_func_op8(obj);
|
object_func_op8(obj);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -175,6 +175,7 @@ void load_avt(const char *filename, uint8_t *dst, int offset) {
|
||||||
g_res.avt[offset + i] = ptr;
|
g_res.avt[offset + i] = ptr;
|
||||||
ptr += 132;
|
ptr += 132;
|
||||||
}
|
}
|
||||||
|
g_res.avt_count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *trigger_lookup_table1(uint8_t num) {
|
static const uint8_t *trigger_lookup_table1(uint8_t num) {
|
||||||
|
@ -259,6 +260,7 @@ void load_sqv(const char *filename, uint8_t *dst, int offset) {
|
||||||
const uint8_t *ptr = dst;
|
const uint8_t *ptr = dst;
|
||||||
const int count = READ_LE_UINT16(ptr); ptr += 6;
|
const int count = READ_LE_UINT16(ptr); ptr += 6;
|
||||||
print_debug(DBG_RESOURCE, "sqv count %d", count);
|
print_debug(DBG_RESOURCE, "sqv count %d", count);
|
||||||
|
assert(offset + count <= MAX_SPR_FRAMES);
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
g_res.spr_frames[offset + i] = ptr;
|
g_res.spr_frames[offset + i] = ptr;
|
||||||
const int h = READ_LE_UINT16(ptr - 4);
|
const int h = READ_LE_UINT16(ptr - 4);
|
||||||
|
@ -268,6 +270,7 @@ void load_sqv(const char *filename, uint8_t *dst, int offset) {
|
||||||
print_debug(DBG_RESOURCE, "sprite %d, dim %d,%d size %d", i, w, h, size);
|
print_debug(DBG_RESOURCE, "sprite %d, dim %d,%d size %d", i, w, h, size);
|
||||||
ptr += size;
|
ptr += size;
|
||||||
}
|
}
|
||||||
|
g_res.spr_count = offset + count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_sql(const char *filename) {
|
void load_sql(const char *filename) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct trigger_t {
|
||||||
#define MAX_SPR_FRAMES 200
|
#define MAX_SPR_FRAMES 200
|
||||||
#define MAX_TRIGGERS 256
|
#define MAX_TRIGGERS 256
|
||||||
#define SOUND_SIZE 29376
|
#define SOUND_SIZE 29376
|
||||||
|
#define SPRITES_COUNT 146
|
||||||
|
|
||||||
#define RESOURCE_FLAGS_DEMO (1 << 0)
|
#define RESOURCE_FLAGS_DEMO (1 << 0)
|
||||||
|
|
||||||
|
@ -34,7 +35,9 @@ struct resource_data_t {
|
||||||
uint8_t *spr_sqv;
|
uint8_t *spr_sqv;
|
||||||
uint8_t *avt_sqv;
|
uint8_t *avt_sqv;
|
||||||
uint8_t *tmp;
|
uint8_t *tmp;
|
||||||
|
int avt_count;
|
||||||
const uint8_t *avt[MAX_AVT];
|
const uint8_t *avt[MAX_AVT];
|
||||||
|
int spr_count;
|
||||||
const uint8_t *spr_frames[MAX_SPR_FRAMES];
|
const uint8_t *spr_frames[MAX_SPR_FRAMES];
|
||||||
uint8_t palette[16 * 3];
|
uint8_t palette[16 * 3];
|
||||||
struct trigger_t triggers[MAX_TRIGGERS];
|
struct trigger_t triggers[MAX_TRIGGERS];
|
||||||
|
|
141
screen.c
141
screen.c
|
@ -5,49 +5,36 @@
|
||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#define MAX_SPRITESHEET_W 1024
|
||||||
|
#define MAX_SPRITESHEET_H 512
|
||||||
|
|
||||||
void screen_init() {
|
void screen_init() {
|
||||||
for (int i = 0; i < MAX_SPRITES; ++i) {
|
|
||||||
g_vars.sprites[i] = &g_vars.sprites_table[i];
|
|
||||||
}
|
|
||||||
for (int i = 0; i < MAX_SPRITES - 1; ++i) {
|
|
||||||
g_vars.sprites[i]->next_sprite = g_vars.sprites[i] + 1;
|
|
||||||
}
|
|
||||||
g_vars.sprites[MAX_SPRITES - 1]->next_sprite = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_clear_sprites() {
|
void screen_clear_sprites() {
|
||||||
g_vars.sprites_count = 0;
|
render_clear_sprites();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_game_sprite(int x, int y, int frame, int xflip) {
|
||||||
|
const uint8_t *p = g_res.spr_frames[frame];
|
||||||
|
const int h = READ_LE_UINT16(p - 4);
|
||||||
|
const int w = READ_LE_UINT16(p - 2);
|
||||||
|
int spr_type = RENDER_SPR_GAME;
|
||||||
|
if (frame >= SPRITES_COUNT) {
|
||||||
|
spr_type = RENDER_SPR_LEVEL;
|
||||||
|
frame -= SPRITES_COUNT;
|
||||||
|
}
|
||||||
|
render_add_sprite(spr_type, frame, x - w / 2, y - h, xflip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_add_sprite(int x, int y, int frame) {
|
void screen_add_sprite(int x, int y, int frame) {
|
||||||
assert(g_vars.sprites_count < MAX_SPRITES);
|
add_game_sprite(x, y, frame, 0);
|
||||||
struct sprite_t *spr = g_vars.sprites[g_vars.sprites_count];
|
|
||||||
spr->xpos = x;
|
|
||||||
spr->ypos = y;
|
|
||||||
spr->frame = g_res.spr_frames[frame];
|
|
||||||
spr->xflip = 0;
|
|
||||||
spr->unk16 = 0;
|
|
||||||
spr->next_sprite = spr + 1;
|
|
||||||
++g_vars.sprites_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_clear_last_sprite() {
|
void screen_clear_last_sprite() {
|
||||||
assert(g_vars.sprites_count >= 0);
|
|
||||||
if (g_vars.sprites_count > 0) {
|
|
||||||
g_vars.sprites[g_vars.sprites_count - 1]->next_sprite = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_redraw_sprites() {
|
void screen_redraw_sprites() {
|
||||||
for (int i = 0; i < g_vars.sprites_count; ++i) {
|
|
||||||
struct sprite_t *spr = g_vars.sprites[i];
|
|
||||||
const uint8_t *p = spr->frame;
|
|
||||||
const int h = READ_LE_UINT16(p - 4);
|
|
||||||
const int w = READ_LE_UINT16(p - 2);
|
|
||||||
const int y = spr->ypos - h;
|
|
||||||
const int x = spr->xpos - w / 2;
|
|
||||||
decode_ega_spr(p, w, w, h, g_res.vga, GAME_SCREEN_W, x, y, spr->xflip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void fade_in_palette() {
|
void fade_in_palette() {
|
||||||
|
@ -61,16 +48,12 @@ void fade_out_palette() {
|
||||||
void screen_adjust_palette_color(int color, int b, int c) {
|
void screen_adjust_palette_color(int color, int b, int c) {
|
||||||
g_res.palette[color * 3 + b] += c;
|
g_res.palette[color * 3 + b] += c;
|
||||||
screen_vsync();
|
screen_vsync();
|
||||||
screen_set_palette();
|
g_sys.set_screen_palette(g_res.palette, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_vsync() {
|
void screen_vsync() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_set_palette() {
|
|
||||||
g_sys.set_screen_palette(g_res.palette, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d) {
|
void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d) {
|
||||||
const int h = READ_LE_UINT16(frame - 4);
|
const int h = READ_LE_UINT16(frame - 4);
|
||||||
assert(a <= h);
|
assert(a <= h);
|
||||||
|
@ -78,7 +61,7 @@ void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d) {
|
||||||
assert(b <= w);
|
assert(b <= w);
|
||||||
const int x = c;
|
const int x = c;
|
||||||
const int y = d + a + 2;
|
const int y = d + a + 2;
|
||||||
decode_ega_spr(frame, w, b, h, g_res.vga, GAME_SCREEN_W, x, y, 0);
|
decode_ega_spr(frame, w, b, h, g_res.vga, GAME_SCREEN_W, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_flip() {
|
void screen_flip() {
|
||||||
|
@ -96,9 +79,9 @@ void screen_unk5() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_unk6() {
|
void screen_unk6() {
|
||||||
// _screen_draw_offset -= 12;
|
// g_vars.screen_draw_offset -= 12;
|
||||||
// screen_do_transition2();
|
// screen_do_transition2();
|
||||||
// _screen_draw_offset += 12;
|
// g_vars.screen_draw_offset += 12;
|
||||||
g_sys.update_screen(g_res.vga, 1);
|
g_sys.update_screen(g_res.vga, 1);
|
||||||
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
|
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
|
||||||
}
|
}
|
||||||
|
@ -156,24 +139,90 @@ void screen_do_transition2() {
|
||||||
void screen_draw_number(int num, int x, int y, int color) {
|
void screen_draw_number(int num, int x, int y, int color) {
|
||||||
extern const uint8_t font_data[];
|
extern const uint8_t font_data[];
|
||||||
y += TILEMAP_OFFSET_Y;
|
y += TILEMAP_OFFSET_Y;
|
||||||
decode_ega_spr(font_data + (num / 10) * 32, 8, 8, 8, g_res.vga, GAME_SCREEN_W, x - 8, y, 0);
|
decode_ega_spr(font_data + (num / 10) * 32, 8, 8, 8, g_res.vga, GAME_SCREEN_W, x - 8, y);
|
||||||
decode_ega_spr(font_data + (num % 10) * 32, 8, 8, 8, g_res.vga, GAME_SCREEN_W, x, y, 0);
|
decode_ega_spr(font_data + (num % 10) * 32, 8, 8, 8, g_res.vga, GAME_SCREEN_W, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_add_game_sprite1(int x, int y, int frame) {
|
void screen_add_game_sprite1(int x, int y, int frame) {
|
||||||
screen_add_sprite(x, y + TILEMAP_OFFSET_Y, frame);
|
add_game_sprite(x, y + TILEMAP_OFFSET_Y, frame, 0);
|
||||||
g_vars.sprites[g_vars.sprites_count - 1]->xflip = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_add_game_sprite2(int x, int y, int frame) {
|
void screen_add_game_sprite2(int x, int y, int frame) {
|
||||||
screen_add_sprite(x, y + TILEMAP_OFFSET_Y, frame);
|
add_game_sprite(x, y + TILEMAP_OFFSET_Y, frame, 1);
|
||||||
g_vars.sprites[g_vars.sprites_count - 1]->xflip = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter) {
|
void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter) {
|
||||||
print_warning("screen_add_game_sprite3");
|
// print_warning("screen_add_game_sprite3");
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter) {
|
void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter) {
|
||||||
print_warning("screen_add_game_sprite4");
|
// print_warning("screen_add_game_sprite4");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_graphics(int spr_type, int start, int end) {
|
||||||
|
struct sys_rect_t r[MAX_SPR_FRAMES];
|
||||||
|
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
|
||||||
|
if (data) {
|
||||||
|
int current_x = 0;
|
||||||
|
int max_w = 0;
|
||||||
|
int current_y = 0;
|
||||||
|
int max_h = 0;
|
||||||
|
for (int i = start; i < end; ++i) {
|
||||||
|
const uint8_t *ptr = g_res.spr_frames[i];
|
||||||
|
const int h = READ_LE_UINT16(ptr - 4);
|
||||||
|
const int w = READ_LE_UINT16(ptr - 2);
|
||||||
|
const int j = i - start;
|
||||||
|
if (current_x + w > MAX_SPRITESHEET_W) {
|
||||||
|
current_y += max_h;
|
||||||
|
if (current_x > max_w) {
|
||||||
|
max_w = current_x;
|
||||||
|
}
|
||||||
|
current_x = 0;
|
||||||
|
max_h = h;
|
||||||
|
decode_ega_spr(ptr, w, w, h, data, MAX_SPRITESHEET_W, current_x, current_y);
|
||||||
|
r[j].x = current_x;
|
||||||
|
r[j].y = current_y;
|
||||||
|
} else {
|
||||||
|
decode_ega_spr(ptr, w, w, h, data, MAX_SPRITESHEET_W, current_x, current_y);
|
||||||
|
r[j].x = current_x;
|
||||||
|
r[j].y = current_y;
|
||||||
|
current_x += w;
|
||||||
|
if (h > max_h) {
|
||||||
|
max_h = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r[j].w = w;
|
||||||
|
r[j].h = h;
|
||||||
|
}
|
||||||
|
assert(max_w <= MAX_SPRITESHEET_W);
|
||||||
|
assert(current_y + max_h <= MAX_SPRITESHEET_H);
|
||||||
|
render_unload_sprites(spr_type);
|
||||||
|
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void screen_load_graphics() {
|
||||||
|
if (g_res.spr_count <= SPRITES_COUNT) {
|
||||||
|
decode_graphics(RENDER_SPR_GAME, 0, SPRITES_COUNT);
|
||||||
|
} else {
|
||||||
|
decode_graphics(RENDER_SPR_LEVEL, SPRITES_COUNT, g_res.spr_count);
|
||||||
|
struct sys_rect_t r[MAX_SPR_FRAMES];
|
||||||
|
static const int FG_TILE_W = 16;
|
||||||
|
static const int FG_TILE_H = 16;
|
||||||
|
uint8_t *data = (uint8_t *)malloc(g_res.avt_count * FG_TILE_W * FG_TILE_H);
|
||||||
|
if (data) {
|
||||||
|
const int pitch = g_res.avt_count * FG_TILE_W;
|
||||||
|
for (int i = 0; i < g_res.avt_count; ++i) {
|
||||||
|
decode_ega_spr(g_res.avt[i], FG_TILE_W, FG_TILE_W, FG_TILE_H, data, pitch, i * FG_TILE_W, 0);
|
||||||
|
r[i].x = i * FG_TILE_W;
|
||||||
|
r[i].y = 0;
|
||||||
|
r[i].w = FG_TILE_W;
|
||||||
|
r[i].h = FG_TILE_H;
|
||||||
|
}
|
||||||
|
render_unload_sprites(RENDER_SPR_FG);
|
||||||
|
render_load_sprites(RENDER_SPR_FG, g_res.avt_count, r, data, g_res.avt_count * FG_TILE_W, FG_TILE_H);
|
||||||
|
free(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
50
sound.c
50
sound.c
|
@ -32,7 +32,7 @@ static const struct {
|
||||||
{ 0x36a6, 0x0574 }
|
{ 0x36a6, 0x0574 }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Amiga, unexotica
|
// Amiga, ExoticA
|
||||||
static const char *_modules[] = {
|
static const char *_modules[] = {
|
||||||
"ALMOST", "mod.almost",
|
"ALMOST", "mod.almost",
|
||||||
"GUNN", "mod.bluesgunnbest",
|
"GUNN", "mod.bluesgunnbest",
|
||||||
|
@ -47,7 +47,7 @@ struct mixerchannel_t {
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int _rate = 22050;
|
static const int _rate = SYS_AUDIO_FREQ;
|
||||||
static struct mixerchannel_t _channel;
|
static struct mixerchannel_t _channel;
|
||||||
static ModPlugFile *_mpf;
|
static ModPlugFile *_mpf;
|
||||||
|
|
||||||
|
@ -74,7 +74,6 @@ static void mix(void *param, uint8_t *buf, int len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_init(int rate) {
|
void sound_init(int rate) {
|
||||||
_rate = rate;
|
|
||||||
ModPlug_Settings mp_settings;
|
ModPlug_Settings mp_settings;
|
||||||
memset(&mp_settings, 0, sizeof(mp_settings));
|
memset(&mp_settings, 0, sizeof(mp_settings));
|
||||||
ModPlug_GetSettings(&mp_settings);
|
ModPlug_GetSettings(&mp_settings);
|
||||||
|
@ -109,7 +108,49 @@ void play_music(int num) {
|
||||||
ModPlug_Unload(_mpf);
|
ModPlug_Unload(_mpf);
|
||||||
_mpf = 0;
|
_mpf = 0;
|
||||||
}
|
}
|
||||||
const char *filename = _modules[num * 2 + 1];
|
const char *filename = _modules[num * 2];
|
||||||
|
if (fio_exists(filename)) { // Amiga
|
||||||
|
int slot = fio_open(filename, 1);
|
||||||
|
int size = fio_size(slot);
|
||||||
|
uint8_t *buf = (uint8_t *)malloc(size);
|
||||||
|
if (buf) {
|
||||||
|
fio_read(slot, buf, size);
|
||||||
|
|
||||||
|
// append samples to the end of the buffer
|
||||||
|
static const int SONG_INFO_LEN = 20;
|
||||||
|
static const int NUM_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
fio_close(sample_slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_mpf = ModPlug_Load(buf, size);
|
||||||
|
}
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
fio_close(slot);
|
||||||
|
} else { // ExoticA
|
||||||
|
filename = _modules[num * 2 + 1];
|
||||||
if (fio_exists(filename)) {
|
if (fio_exists(filename)) {
|
||||||
int slot = fio_open(filename, 1);
|
int slot = fio_open(filename, 1);
|
||||||
int size = fio_size(slot);
|
int size = fio_size(slot);
|
||||||
|
@ -121,5 +162,6 @@ void play_music(int num) {
|
||||||
}
|
}
|
||||||
fio_close(slot);
|
fio_close(slot);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
g_sys.unlock_audio();
|
g_sys.unlock_audio();
|
||||||
}
|
}
|
||||||
|
|
17
sys.h
17
sys.h
|
@ -23,6 +23,11 @@ struct input_t {
|
||||||
|
|
||||||
typedef void (*sys_audio_cb)(void *, uint8_t *data, int len);
|
typedef void (*sys_audio_cb)(void *, uint8_t *data, int len);
|
||||||
|
|
||||||
|
struct sys_rect_t {
|
||||||
|
int x, y;
|
||||||
|
int w, h;
|
||||||
|
};
|
||||||
|
|
||||||
struct sys_t {
|
struct sys_t {
|
||||||
struct input_t input;
|
struct input_t input;
|
||||||
int (*init)();
|
int (*init)();
|
||||||
|
@ -45,4 +50,16 @@ struct sys_t {
|
||||||
|
|
||||||
extern struct sys_t g_sys;
|
extern struct sys_t g_sys;
|
||||||
|
|
||||||
|
#define RENDER_SPR_GAME 0 /* player sprites */
|
||||||
|
#define RENDER_SPR_LEVEL 1 /* level sprites */
|
||||||
|
#define RENDER_SPR_FONT 2 /* font (digits) */
|
||||||
|
#define RENDER_SPR_FG 3 /* foreground tiles */
|
||||||
|
|
||||||
|
extern void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h);
|
||||||
|
extern void render_unload_sprites(int spr_type);
|
||||||
|
extern void render_add_sprite(int spr_type, int frame, int x, int y, int xflip);
|
||||||
|
extern void render_clear_sprites();
|
||||||
|
extern void render_draw_tilemap(int x, int y);
|
||||||
|
extern void render_draw_image();
|
||||||
|
|
||||||
#endif /* SYS_H__ */
|
#endif /* SYS_H__ */
|
||||||
|
|
100
sys_sdl2.c
100
sys_sdl2.c
|
@ -8,6 +8,24 @@
|
||||||
static const int SCALE = 2;
|
static const int SCALE = 2;
|
||||||
static const int FADE_STEPS = 16;
|
static const int FADE_STEPS = 16;
|
||||||
|
|
||||||
|
struct spritesheet_t {
|
||||||
|
int count;
|
||||||
|
SDL_Rect *r;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct spritesheet_t _spritesheets[4];
|
||||||
|
|
||||||
|
struct sprite_t {
|
||||||
|
int sheet;
|
||||||
|
int num;
|
||||||
|
int x, y;
|
||||||
|
bool xflip;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sprite_t _sprites[128];
|
||||||
|
static int _sprites_count;
|
||||||
|
|
||||||
static int _screen_w;
|
static int _screen_w;
|
||||||
static int _screen_h;
|
static int _screen_h;
|
||||||
static SDL_Window *_window;
|
static SDL_Window *_window;
|
||||||
|
@ -62,7 +80,7 @@ static void sdl2_set_screen_size(int w, int h, const char *caption) {
|
||||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); /* nearest pixel sampling */
|
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "0"); /* nearest pixel sampling */
|
||||||
const int window_w = w * SCALE;
|
const int window_w = w * SCALE;
|
||||||
const int window_h = h * SCALE; // * 4 / 3;
|
const int window_h = h * SCALE; // * 4 / 3;
|
||||||
_window = SDL_CreateWindow(caption, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_w, window_h, 0);
|
_window = SDL_CreateWindow(caption, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, window_w, window_h, SDL_WINDOW_RESIZABLE);
|
||||||
_renderer = SDL_CreateRenderer(_window, -1, 0);
|
_renderer = SDL_CreateRenderer(_window, -1, 0);
|
||||||
print_debug(DBG_SYSTEM, "set_screen_size %d,%d", _screen_w, _screen_h);
|
print_debug(DBG_SYSTEM, "set_screen_size %d,%d", _screen_w, _screen_h);
|
||||||
_screen_buffer = (uint32_t *)calloc(_screen_w * _screen_h, sizeof(uint32_t));
|
_screen_buffer = (uint32_t *)calloc(_screen_w * _screen_h, sizeof(uint32_t));
|
||||||
|
@ -97,7 +115,7 @@ static void sdl2_set_copper_bars(const uint16_t *data) {
|
||||||
_copper_color = (data[0] - 0x180) / 2;
|
_copper_color = (data[0] - 0x180) / 2;
|
||||||
const uint16_t *src = data + 1;
|
const uint16_t *src = data + 1;
|
||||||
uint32_t *dst = _copper_palette;
|
uint32_t *dst = _copper_palette;
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < COPPER_BARS_H / 5; ++i) {
|
||||||
const int j = i + 1;
|
const int j = i + 1;
|
||||||
*dst++ = convert_amiga_color(src[j]);
|
*dst++ = convert_amiga_color(src[j]);
|
||||||
*dst++ = convert_amiga_color(src[i]);
|
*dst++ = convert_amiga_color(src[i]);
|
||||||
|
@ -145,14 +163,17 @@ static void sdl2_fade_out_palette() {
|
||||||
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) {
|
||||||
|
if (j / 2 < COPPER_BARS_H) {
|
||||||
|
const uint32_t line_color = _copper_palette[j / 2];
|
||||||
for (int i = 0; i < _screen_w; ++i) {
|
for (int i = 0; i < _screen_w; ++i) {
|
||||||
if (*p == _copper_color && j / 2 < COPPER_BARS_H) {
|
_screen_buffer[j * _screen_w + i] = (p[i] == _copper_color) ? line_color : _screen_palette[p[i]];
|
||||||
_screen_buffer[j * _screen_w + i] = _copper_palette[j / 2];
|
}
|
||||||
} else {
|
} else {
|
||||||
_screen_buffer[j * _screen_w + i] = _screen_palette[*p];
|
for (int i = 0; i < _screen_w; ++i) {
|
||||||
|
_screen_buffer[j * _screen_w + i] = _screen_palette[p[i]];
|
||||||
}
|
}
|
||||||
++p;
|
|
||||||
}
|
}
|
||||||
|
p += _screen_w;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < _screen_w * _screen_h; ++i) {
|
for (int i = 0; i < _screen_w * _screen_h; ++i) {
|
||||||
|
@ -163,6 +184,23 @@ static void sdl2_update_screen(const uint8_t *p, int present) {
|
||||||
if (present) {
|
if (present) {
|
||||||
SDL_RenderClear(_renderer);
|
SDL_RenderClear(_renderer);
|
||||||
SDL_RenderCopy(_renderer, _texture, 0, 0);
|
SDL_RenderCopy(_renderer, _texture, 0, 0);
|
||||||
|
|
||||||
|
// sprites
|
||||||
|
for (int i = 0; i < _sprites_count; ++i) {
|
||||||
|
struct sprite_t *spr = &_sprites[i];
|
||||||
|
struct spritesheet_t *sheet = &_spritesheets[spr->sheet];
|
||||||
|
SDL_Rect r;
|
||||||
|
r.x = spr->x * SCALE;
|
||||||
|
r.y = spr->y * SCALE;
|
||||||
|
r.w = sheet->r[spr->num].w * SCALE;
|
||||||
|
r.h = sheet->r[spr->num].h * SCALE;
|
||||||
|
if (!spr->xflip) {
|
||||||
|
SDL_RenderCopy(_renderer, sheet->texture, &sheet->r[spr->num], &r);
|
||||||
|
} else {
|
||||||
|
SDL_RenderCopyEx(_renderer, sheet->texture, &sheet->r[spr->num], &r, 0., 0, SDL_FLIP_HORIZONTAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_RenderPresent(_renderer);
|
SDL_RenderPresent(_renderer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -283,3 +321,53 @@ struct sys_t g_sys = {
|
||||||
.lock_audio = sdl2_lock_audio,
|
.lock_audio = sdl2_lock_audio,
|
||||||
.unlock_audio = sdl2_unlock_audio,
|
.unlock_audio = sdl2_unlock_audio,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h) {
|
||||||
|
assert(spr_type < ARRAYSIZE(_spritesheets));
|
||||||
|
struct spritesheet_t *spr_sheet = &_spritesheets[spr_type];
|
||||||
|
spr_sheet->count = count;
|
||||||
|
spr_sheet->r = (SDL_Rect *)malloc(count * sizeof(SDL_Rect));
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
SDL_Rect *rect = &spr_sheet->r[i];
|
||||||
|
rect->x = r[i].x;
|
||||||
|
rect->y = r[i].y;
|
||||||
|
rect->w = r[i].w;
|
||||||
|
rect->h = r[i].h;
|
||||||
|
}
|
||||||
|
uint32_t *argb = (uint32_t *)malloc(w * h * sizeof(uint32_t));
|
||||||
|
if (!argb) {
|
||||||
|
print_warning("Failed to allocate RGB buffer for sprites type %d", spr_type);
|
||||||
|
} else {
|
||||||
|
spr_sheet->texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
|
||||||
|
SDL_SetTextureBlendMode(spr_sheet->texture, SDL_BLENDMODE_BLEND);
|
||||||
|
for (int i = 0; i < w * h; ++i) {
|
||||||
|
argb[i] = (data[i] == 0) ? 0 : (0xFF000000 | _screen_palette[data[i]]);
|
||||||
|
}
|
||||||
|
SDL_UpdateTexture(spr_sheet->texture, 0, argb, w * sizeof(uint32_t));
|
||||||
|
free(argb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_unload_sprites(int spr_type) {
|
||||||
|
struct spritesheet_t *spr_sheet = &_spritesheets[spr_type];
|
||||||
|
free(spr_sheet->r);
|
||||||
|
if (spr_sheet->texture) {
|
||||||
|
SDL_DestroyTexture(spr_sheet->texture);
|
||||||
|
}
|
||||||
|
memset(spr_sheet, 0, sizeof(struct spritesheet_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_add_sprite(int spr_type, int frame, int x, int y, int xflip) {
|
||||||
|
assert(_sprites_count < ARRAYSIZE(_sprites));
|
||||||
|
struct sprite_t *spr = &_sprites[_sprites_count];
|
||||||
|
spr->sheet = spr_type;
|
||||||
|
spr->num = frame;
|
||||||
|
spr->x = x;
|
||||||
|
spr->y = y;
|
||||||
|
spr->xflip = xflip;
|
||||||
|
++_sprites_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_clear_sprites() {
|
||||||
|
_sprites_count = 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue