diff --git a/game.c b/game.c index a0c5620..389cc1c 100644 --- a/game.c +++ b/game.c @@ -23,13 +23,13 @@ void update_input() { g_vars.inp_key_right = ((g_sys.input.direction & INPUT_DIRECTION_RIGHT) != 0) || g_vars.inp_keyboard[0x4D] || g_vars.inp_keyboard[0x79]; g_vars.inp_key_up = ((g_sys.input.direction & INPUT_DIRECTION_UP) != 0) || g_vars.inp_keyboard[0x48] || g_vars.inp_keyboard[0x7C]; g_vars.inp_key_down = ((g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0) || g_vars.inp_keyboard[0x50] || g_vars.inp_keyboard[0x7B]; - g_vars.inp_key_space = (g_sys.input.space != 0) || g_vars.inp_keyboard[0x39] || g_vars.inp_keyboard[0x77]; + g_vars.inp_key_space = g_sys.input.space || g_vars.inp_keyboard[0x39] || g_vars.inp_keyboard[0x77]; g_vars.inp_key_tab = g_vars.inp_keyboard[0xF] || g_vars.inp_keyboard[0x78]; } void do_title_screen() { const uint32_t timestamp = g_sys.get_timestamp() + 20 * 1000; - load_img(g_options.amiga_data ? "blues.lbm" : "pres.sqz"); + load_img(g_options.amiga_data ? "blues.lbm" : "pres.sqz", GAME_SCREEN_W); fade_in_palette(); do { update_input(); @@ -64,7 +64,7 @@ void do_select_player() { int frame2 = 1; const int color_rgb = 2; const int colors_count = 25; - load_img(g_options.amiga_data ? "choix.lbm" : "choix.sqz"); + load_img(g_options.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W); screen_load_graphics(); screen_clear_sprites(); do { @@ -250,8 +250,8 @@ static void do_inter_screen_helper(int xpos, int ypos, int c) { static void do_inter_screen() { static const uint8_t xpos[] = { 0xFA, 0x50, 0xF0, 0xC8, 0x50, 0x50 }; static const uint8_t ypos[] = { 0xAA, 0x37, 0x28, 0x5F, 0xA5, 0xAA }; - load_img(g_options.amiga_data ? "inter.lbm" : "inter.sqz"); - g_vars.screen_h = 199; + load_img(g_options.amiga_data ? "inter.lbm" : "inter.sqz", GAME_SCREEN_W); + g_vars.screen_draw_h = GAME_SCREEN_H - 1; screen_clear_sprites(); if (g_vars.level > 1) { for (int i = 0; i < g_vars.level - 1; ++i) { @@ -292,8 +292,8 @@ void game_main() { g_vars.screen_w = GAME_SCREEN_W; g_vars.screen_h = GAME_SCREEN_H; g_vars.screen_draw_offset = 0; - screen_flip(); screen_init(); + screen_flip(); g_vars.start_level = 0; if (g_options.amiga_data) { load_spr("sprite", g_res.spr_sqv, 0); diff --git a/game.h b/game.h index feab382..903c895 100644 --- a/game.h +++ b/game.h @@ -8,8 +8,8 @@ #define GAME_SCREEN_H 200 #define TILEMAP_OFFSET_Y 14 -#define TILEMAP_SCREEN_W 320 -#define TILEMAP_SCREEN_H 160 +#define TILEMAP_SCREEN_W GAME_SCREEN_W +#define TILEMAP_SCREEN_H (GAME_SCREEN_H - 40) #define PLAYER_JAKE 0 #define PLAYER_ELWOOD 1 @@ -152,8 +152,8 @@ struct vars_t { int screen_tilemap_xoffset, screen_tilemap_yoffset; int screen_tilemap_size_w, screen_tilemap_size_h; int screen_scrolling_dirmask, screen_unk1; - uint16_t screen_draw_offset; - uint16_t screen_tile_lut[256]; + int screen_draw_h, screen_draw_offset; + int screen_tile_lut[256]; int level_completed_flag; int play_level_flag; int game_over_flag; @@ -238,7 +238,7 @@ extern void level_call_object_func(struct object_t *); /* screen.c */ extern void screen_init(); -extern void screen_clear_sprites(); // _sprites_count = 0 +extern void screen_clear_sprites(); extern void screen_add_sprite(int x, int y, int frame); extern void screen_clear_last_sprite(); extern void screen_redraw_sprites(); @@ -246,17 +246,15 @@ extern void fade_in_palette(); extern void fade_out_palette(); extern void screen_adjust_palette_color(int color, int b, int c); extern void screen_vsync(); -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 fh, int fw, int x, int y); extern void screen_flip(); extern void screen_unk4(); extern void screen_unk5(); extern void screen_unk6(); -extern void screen_copy_tilemap2(int a, int b, int c, int d); -extern void screen_copy_tilemap(int a); extern void screen_do_transition1(int a); +extern void screen_do_transition2(); extern void screen_clear(int a); extern void screen_draw_tile(int tile, int dst, int type); -extern void screen_do_transition2(); extern void screen_draw_number(int num, int x, int y, int color); extern void screen_add_game_sprite1(int x, int y, int frame); extern void screen_add_game_sprite2(int x, int y, int frame); @@ -265,7 +263,7 @@ extern void screen_add_game_sprite4(int x, int y, int frame, int blinking_counte extern void screen_load_graphics(); /* sound.c */ -extern void sound_init(int rate); +extern void sound_init(); extern void sound_fini(); extern void play_sound(int num); extern void play_music(int num); diff --git a/level.c b/level.c index aecad1f..a78a5bb 100644 --- a/level.c +++ b/level.c @@ -353,22 +353,6 @@ static void do_level_update_scrolling2() { if ((g_vars.level_loop_counter & 3) == 0) { do_level_update_tiles_anim(); } - if (g_vars.screen_tilemap_size_w == 20) { - if (g_vars.screen_tilemap_size_h == 10) { - screen_copy_tilemap(2); - } else { - screen_copy_tilemap2(g_vars.screen_tilemap_xoffset + g_vars.screen_tilemap_yoffset, 0, g_vars.screen_tilemap_size_w, g_vars.screen_tilemap_size_h); - screen_copy_tilemap2(g_vars.screen_tilemap_yoffset, 6400 - g_vars.screen_tilemap_xoffset, g_vars.screen_tilemap_size_w, 10 - g_vars.screen_tilemap_size_h); - } - } else if (g_vars.screen_tilemap_size_h == 10) { - screen_copy_tilemap2(g_vars.screen_tilemap_xoffset + g_vars.screen_tilemap_yoffset, 0, g_vars.screen_tilemap_size_w, g_vars.screen_tilemap_size_h); - screen_copy_tilemap2(g_vars.screen_tilemap_xoffset, 40 - g_vars.screen_tilemap_yoffset, 20 - g_vars.screen_tilemap_size_w, g_vars.screen_tilemap_size_h); - } else { - screen_copy_tilemap2(g_vars.screen_tilemap_xoffset + g_vars.screen_tilemap_yoffset, 0, g_vars.screen_tilemap_size_w, g_vars.screen_tilemap_size_h); - screen_copy_tilemap2(g_vars.screen_tilemap_xoffset, 40 - g_vars.screen_tilemap_yoffset, 20 - g_vars.screen_tilemap_size_w, g_vars.screen_tilemap_size_h); - screen_copy_tilemap2(g_vars.screen_tilemap_yoffset, 6400 - g_vars.screen_tilemap_xoffset, g_vars.screen_tilemap_size_w, 10 - g_vars.screen_tilemap_size_h); - screen_copy_tilemap2(0, 40 - g_vars.screen_tilemap_yoffset + 6400 - g_vars.screen_tilemap_xoffset, 20 - g_vars.screen_tilemap_size_w, 10 - g_vars.screen_tilemap_size_h); - } } void do_level_drop_grabbed_object(struct object_t *obj) { @@ -993,7 +977,7 @@ static void do_level_update_grabbed_object(struct object_t *obj) { void do_level_update_panel_lifes(struct object_t *obj) { struct object_t *obj39 = &g_vars.objects[OBJECT_NUM_PLAYER1]; struct object_t *obj40 = &g_vars.objects[OBJECT_NUM_PLAYER2]; - g_vars.screen_h = 172; + g_vars.screen_draw_h = 172; if (!g_vars.two_players_flag) { static const uint16_t data[] = { 216, 232, 248, 264, 280, 296 }; for (int i = 0; i < obj->data51; ++i) { @@ -1066,14 +1050,11 @@ void do_level_update_panel_lifes(struct object_t *obj) { } } } - g_vars.screen_h = TILEMAP_SCREEN_H; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; } static void do_level_update_panel_vinyls(struct object_t *obj) { - // if (!_screen_panel_drawn_flag) { - // return; - // } - g_vars.screen_h = 172; + g_vars.screen_draw_h = 172; if (obj->vinyls_count > 99) { obj->vinyls_count -= 100; if (!g_vars.two_players_flag && obj->data51 < 5) { @@ -1101,15 +1082,12 @@ static void do_level_update_panel_vinyls(struct object_t *obj) { } g_vars.vinyls_count = obj->vinyls_count; } - g_vars.screen_h = TILEMAP_SCREEN_H; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; } static void do_level_update_panel_2nd_player() { struct object_t *obj = &g_vars.objects[OBJECT_NUM_PLAYER2]; - // if (!_screen_panel_drawn_flag) { - // return; - // } - g_vars.screen_h = 172; + g_vars.screen_draw_h = 172; if (obj->vinyls_count > 99) { obj->vinyls_count = 0; if (!g_vars.two_players_flag && obj->data51 < 5) { @@ -1127,13 +1105,13 @@ static void do_level_update_panel_2nd_player() { screen_draw_number(obj->vinyls_count, 280, 163, 2); g_vars.vinyls_count = obj->vinyls_count; } - g_vars.screen_h = TILEMAP_SCREEN_H; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; } static void draw_level_panel() { struct object_t *obj39 = &g_vars.objects[OBJECT_NUM_PLAYER1]; struct object_t *obj40 = &g_vars.objects[OBJECT_NUM_PLAYER2]; - g_vars.screen_h = 172; + g_vars.screen_draw_h = 172; g_vars.vinyls_count = 0; if (!g_vars.two_players_flag) { screen_draw_frame(g_res.spr_frames[123], 12, 320, 0, -12); @@ -1184,7 +1162,7 @@ static void draw_level_panel() { } } } - g_vars.screen_h = TILEMAP_SCREEN_H; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; } void do_level_enter_door(struct object_t *obj) { @@ -1192,7 +1170,6 @@ void do_level_enter_door(struct object_t *obj) { for (int i = 0; i < MAX_DOORS; ++i) { if (obj->xpos16 == g_vars.doors[i].src_x16 && obj->ypos16 == g_vars.doors[i].src_y16) { screen_do_transition1(0); - // _draw_last_sprite_flag = 0; obj->xpos = g_vars.doors[i].dst_x16 << 4; obj->ypos = g_vars.doors[i].dst_y16 << 4; if (obj->ypos > g_vars.screen_tilemap_h) { @@ -1647,7 +1624,7 @@ static void do_level_handle_object_bonus_collision(struct object_t *obj, struct void do_level_player_hit(struct object_t *obj) { if (obj->blinking_counter == 0) { - g_vars.screen_h = 172; + g_vars.screen_draw_h = 172; if (obj->data51 > 0) { --obj->data51; do_level_update_panel_lifes(obj); @@ -1655,7 +1632,7 @@ void do_level_player_hit(struct object_t *obj) { if (obj->special_anim != 16) { obj->blinking_counter = 75; } - g_vars.screen_h = TILEMAP_SCREEN_H; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; } } @@ -2079,7 +2056,6 @@ static void do_level_update_objects() { if (g_vars.level_completed_flag) { ++g_vars.update_objects_counter; if (g_vars.update_objects_counter > 50) { - // _draw_last_sprite_flag = 0; if (g_vars.level < (MAX_LEVELS - 1)) { ++g_vars.level; } else { @@ -2129,7 +2105,6 @@ static void do_level_update_objects() { if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) { g_vars.play_level_flag = 0; } - // _draw_last_sprite_flag = 0; g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; screen_unk5(); g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40; @@ -2189,11 +2164,10 @@ void do_level() { g_vars.game_over_flag = 0; g_vars.level_completed_flag = 0; g_vars.quit_level_flag = 0; - // _screen_panel_drawn_flag = 0; g_vars.player2_scrolling_flag = 0; - g_vars.screen_h = TILEMAP_SCREEN_H; - // _draw_last_sprite_flag = 0; + g_vars.screen_draw_h = TILEMAP_SCREEN_H; g_vars.found_music_instrument_flag = 0; + render_set_sprites_clipping_rect(0, TILEMAP_OFFSET_Y, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H - TILEMAP_OFFSET_Y); do { const uint32_t timestamp = g_sys.get_timestamp(); update_input(); @@ -2217,26 +2191,18 @@ void do_level() { // demo do_level_update_scrolling2(); do_level_update_objects(); - if (1) { // if (_draw_last_sprite_flag != 0) { - screen_clear_last_sprite(); - screen_redraw_sprites(); - if (!g_options.amiga_data) { - draw_foreground_tiles(); - } + screen_clear_last_sprite(); + screen_redraw_sprites(); + if (!g_options.amiga_data) { + draw_foreground_tiles(); } ++g_vars.level_loop_counter; - if (1) { // (!_screen_panel_drawn_flag) { - draw_level_panel(); - screen_unk6(); - // _screen_panel_drawn_flag = 1; - } else { - screen_flip(); - g_vars.screen_draw_offset ^= 0x2000; - } + draw_level_panel(); + screen_unk6(); + const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp(); g_sys.sleep(diff < 10 ? 10 : diff); screen_clear_sprites(); - // _draw_last_sprite_flag = 1; } while (!g_sys.input.quit && !g_vars.quit_level_flag); g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; diff --git a/main.c b/main.c index 5ded4c7..5edb5f1 100644 --- a/main.c +++ b/main.c @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) { g_options.amiga_copper_bars = true; g_options.amiga_colors = true; // g_options.amiga_data = true; - g_options.amiga_status_bar = true; + // g_options.amiga_status_bar = true; const char *data_path = DEFAULT_DATA_PATH; int scale_factor = DEFAULT_SCALE_FACTOR; const char *scale_filter = DEFAULT_SCALE_FILTER; @@ -87,10 +87,10 @@ int main(int argc, char *argv[]) { } } fio_init(data_path); - res_init(); + res_init(GAME_SCREEN_W * GAME_SCREEN_H); g_sys.init(); g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, "Blues Brothers", scale_factor, scale_filter, fullscreen); - sound_init(SYS_AUDIO_FREQ); + sound_init(); game_main(); sound_fini(); g_sys.fini(); diff --git a/resource.c b/resource.c index 8ee8c36..1cb7463 100644 --- a/resource.c +++ b/resource.c @@ -7,7 +7,7 @@ struct resource_data_t g_res; -void res_init() { +void res_init(int vga_size) { static const int SQL_SIZE = 640 * 25; g_res.sql = (uint8_t *)malloc(SQL_SIZE); if (!g_res.sql) { @@ -23,15 +23,14 @@ void res_init() { if (!g_res.avt_sqv) { print_error("Failed to allocate avt buffer, %d bytes", AVT_SQV_SIZE); } - static const int TMP_SIZE = 32000 + 64000; - g_res.tmp = (uint8_t *)malloc(TMP_SIZE); + const int tmp_size = 32000 + vga_size; + g_res.tmp = (uint8_t *)malloc(tmp_size); if (!g_res.tmp) { - print_error("Failed to allocate tmp buffer, %d bytes", TMP_SIZE); + print_error("Failed to allocate tmp buffer, %d bytes", tmp_size); } - static const int VGA_SIZE = 320 * 200; - g_res.vga = (uint8_t *)malloc(VGA_SIZE); + g_res.vga = (uint8_t *)malloc(vga_size); if (!g_res.vga) { - print_error("Failed to allocate vga buffer, %d bytes", VGA_SIZE); + print_error("Failed to allocate vga buffer, %d bytes", vga_size); } static const int TILES_SIZE = 640 * 200; g_res.tiles = (uint8_t *)malloc(TILES_SIZE); @@ -54,12 +53,19 @@ void res_init() { void res_fini() { free(g_res.sql); + g_res.sql = 0; free(g_res.spr_sqv); + g_res.spr_sqv = 0; free(g_res.avt_sqv); + g_res.avt_sqv = 0; free(g_res.tmp); + g_res.tmp = 0; free(g_res.vga); + g_res.vga = 0; free(g_res.tiles); + g_res.tiles = 0; free(g_res.snd); + g_res.snd = 0; } int read_file(const char *filename, uint8_t *dst, int size) { @@ -244,7 +250,7 @@ void load_ck(const char *filename, uint16_t offset) { g_sys.set_screen_palette(g_res.palette, 16); } -void load_img(const char *filename) { +void load_img(const char *filename, int screen_w) { int size; const char *ext = strrchr(filename, '.'); if (ext && strcmp(ext + 1, "lbm") == 0) { @@ -253,7 +259,7 @@ void load_img(const char *filename) { size = read_compressed_file(filename, g_res.tmp); } assert(size <= 32000); - load_iff(g_res.tmp, size, g_res.tmp + 32000, 320); + load_iff(g_res.tmp, size, g_res.tmp + 32000, screen_w); g_sys.set_screen_palette(g_res.palette, 16); g_sys.update_screen(g_res.tmp + 32000, 0); memcpy(g_res.vga, g_res.tmp + 32000, 64000); diff --git a/resource.h b/resource.h index 8dd7435..cf0e1b1 100644 --- a/resource.h +++ b/resource.h @@ -49,7 +49,7 @@ struct resource_data_t { extern struct resource_data_t g_res; -extern void res_init(); +extern void res_init(int vga_size); extern void res_fini(); extern int read_file(const char *filename, uint8_t *dst, int size); extern int read_compressed_file(const char *filename, uint8_t *dst); @@ -57,7 +57,7 @@ extern void load_avt(const char *filename, uint8_t *dst, int offset); extern void load_bin(const char *filename); extern void load_blk(const char *filename); extern void load_ck(const char *filename, uint16_t offset); -extern void load_img(const char *filename); +extern void load_img(const char *filename, int screen_w); extern void load_m(const char *filename); extern void load_spr(const char *filename, uint8_t *dst, int offset); extern void load_sqv(const char *filename, uint8_t *dst, int offset); diff --git a/screen.c b/screen.c index 659a116..34fa192 100644 --- a/screen.c +++ b/screen.c @@ -9,6 +9,7 @@ #define MAX_SPRITESHEET_H 512 void screen_init() { + memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); } void screen_clear_sprites() { @@ -54,9 +55,14 @@ void screen_adjust_palette_color(int color, int b, int c) { void screen_vsync() { } -void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d) { - const int x = c; - const int y = d + a + 2; +void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y) { + if (GAME_SCREEN_W > 320) { + x += (GAME_SCREEN_W - 320) / 2; + } + if (GAME_SCREEN_H > 200 && y == 161) { // align to the bottom + y += GAME_SCREEN_H - 200; + } + y += fh + 2; if (g_options.amiga_status_bar) { if (frame == g_res.spr_frames[123] || frame == g_res.spr_frames[124]) { // top or bottom status bar for (int x = 0; x < GAME_SCREEN_W; x += 16) { @@ -67,10 +73,10 @@ void screen_draw_frame(const uint8_t *frame, int a, int b, int c, int d) { } } else { const int h = READ_LE_UINT16(frame - 4); - assert(a <= h); + assert(fh <= h); const int w = READ_LE_UINT16(frame - 2); - assert(b <= w); - decode_spr(frame, w, b, h, 4, g_res.vga, GAME_SCREEN_W, x, y, false); + assert(fw <= w); + decode_spr(frame, w, fw, h, 4, g_res.vga, GAME_SCREEN_W, x, y, false); } } @@ -96,12 +102,6 @@ void screen_unk6() { memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); } -void screen_copy_tilemap2(int a, int b, int c, int d) { -} - -void screen_copy_tilemap(int a) { -} - static void screen_unk13(int a) { } @@ -125,13 +125,17 @@ void screen_do_transition1(int a) { } } +void screen_do_transition2() { + print_warning("screen_do_transition2"); +} + void screen_clear(int a) { memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); } void screen_draw_tile(int tile, int dst, int type) { - int y = (dst / 640) * 16 + TILEMAP_OFFSET_Y; - int x = (dst % 640) / 2 * 16; + const int y = (dst / 640) * 16 + TILEMAP_OFFSET_Y; + const int x = (dst % 640) / 2 * 16; const uint8_t *src = g_res.tiles + tile * 16; if (type == 4) { src += 320; @@ -142,10 +146,6 @@ void screen_draw_tile(int tile, int dst, int type) { } } -void screen_do_transition2() { - print_warning("screen_do_transition2"); -} - static void draw_number_amiga(int digit, int x, int y) { extern const uint8_t icon7086[]; // 01 extern const uint8_t icon70ea[]; // 23 diff --git a/sound.c b/sound.c index a934f3a..85bbfa4 100644 --- a/sound.c +++ b/sound.c @@ -73,14 +73,14 @@ static void mix(void *param, uint8_t *buf, int len) { } } -void sound_init(int rate) { +void sound_init() { ModPlug_Settings mp_settings; memset(&mp_settings, 0, sizeof(mp_settings)); ModPlug_GetSettings(&mp_settings); mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION; mp_settings.mChannels = 1; mp_settings.mBits = 16; - mp_settings.mFrequency = rate; + mp_settings.mFrequency = _rate; mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; mp_settings.mLoopCount = -1; ModPlug_SetSettings(&mp_settings); diff --git a/sys.h b/sys.h index 83e1f53..fb3745a 100644 --- a/sys.h +++ b/sys.h @@ -55,5 +55,6 @@ extern void render_load_sprites(int spr_type, int count, const struct sys_rect_t 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_set_sprites_clipping_rect(int x, int y, int w, int h); #endif /* SYS_H__ */ diff --git a/sys_sdl2.c b/sys_sdl2.c index 67a909c..31e96c7 100644 --- a/sys_sdl2.c +++ b/sys_sdl2.c @@ -24,6 +24,7 @@ struct sprite_t { static struct sprite_t _sprites[128]; static int _sprites_count; +static SDL_Rect _sprites_cliprect; static int _screen_w; static int _screen_h; @@ -116,6 +117,10 @@ static void sdl2_set_screen_size(int w, int h, const char *caption, int scale, c static const uint32_t pfmt = SDL_PIXELFORMAT_RGB888; _texture = SDL_CreateTexture(_renderer, pfmt, SDL_TEXTUREACCESS_STREAMING, _screen_w, _screen_h); _fmt = SDL_AllocFormat(pfmt); + _sprites_cliprect.x = 0; + _sprites_cliprect.y = 0; + _sprites_cliprect.w = w; + _sprites_cliprect.h = h; } static uint32_t convert_amiga_color(uint16_t color) { @@ -212,9 +217,13 @@ static void sdl2_update_screen(const uint8_t *p, int present) { SDL_RenderCopy(_renderer, _texture, 0, 0); // sprites + SDL_RenderSetClipRect(_renderer, &_sprites_cliprect); for (int i = 0; i < _sprites_count; ++i) { - struct sprite_t *spr = &_sprites[i]; + const struct sprite_t *spr = &_sprites[i]; struct spritesheet_t *sheet = &_spritesheets[spr->sheet]; + if (spr->num >= sheet->count) { + continue; + } SDL_Rect r; r.x = spr->x; r.y = spr->y; @@ -226,6 +235,7 @@ static void sdl2_update_screen(const uint8_t *p, int present) { SDL_RenderCopyEx(_renderer, sheet->texture, &sheet->r[spr->num], &r, 0., 0, SDL_FLIP_HORIZONTAL); } } + SDL_RenderSetClipRect(_renderer, 0); SDL_RenderPresent(_renderer); } @@ -506,3 +516,10 @@ void render_add_sprite(int spr_type, int frame, int x, int y, int xflip) { void render_clear_sprites() { _sprites_count = 0; } + +void render_set_sprites_clipping_rect(int x, int y, int w, int h) { + _sprites_cliprect.x = x; + _sprites_cliprect.y = y; + _sprites_cliprect.w = w; + _sprites_cliprect.h = h; +}