From 9d70ca5872e48a608622dc53eeee193eeb95f27c Mon Sep 17 00:00:00 2001 From: Gregory Montoir Date: Sun, 13 Mar 2022 06:41:23 +0800 Subject: [PATCH] Import blues from c1e25536 --- README.md | 6 +- bb/game.c | 28 ++-- bb/game.h | 12 +- bb/level.c | 48 ++---- bb/resource.c | 4 +- bb/screen.c | 36 +++-- intern.h | 4 +- ja/game.c | 7 +- ja/game.h | 2 +- ja/level.c | 14 +- ja/screen.c | 13 +- ja/unpack.c | 2 +- main.c | 63 ++++---- p2/game.c | 27 ++-- p2/game.h | 2 +- p2/level.c | 7 +- p2/screen.c | 6 +- sys.h | 8 +- sys_psp.c | 428 ++++++++++++++++++++++++++++++++++++++++++++++++++ sys_sdl2.c | 115 ++++++++------ util.c | 8 + util.h | 4 + 22 files changed, 635 insertions(+), 209 deletions(-) create mode 100644 sys_psp.c diff --git a/README.md b/README.md index 1aed3a1..5d99820 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ The data files of the DOS version, full game or [demo](http://cd.textfiles.com/c ## Changes -Compared to the original DOS executables, the rewritten engines feature : +Compared to the original DOS executables, the rewritten engines feature: - horizontal scrolling - configurable screen size -- game cheats : unlimited lifes and energy, no hit +- game cheats: unlimited lifes and energy, no hit ## Running @@ -66,4 +66,4 @@ Usage: blues [OPTIONS]... ## Downloads -[blues-sdl2-win32.zip](https://www.dropbox.com/s/vv8mh0vrk8l6xro/blues-gh-sdl2-win32.zip?dl=0) - Win32 executable +[blues-sdl2-win32.zip](https://www.dropbox.com/s/rybnnn4s3rmicva/blues-gh-sdl2-win32.zip?dl=0) - Win32 executable diff --git a/bb/game.c b/bb/game.c index 5515d6a..ad780b3 100644 --- a/bb/game.c +++ b/bb/game.c @@ -23,12 +23,12 @@ struct vars_t g_vars; void update_input() { g_sys.process_events(); - g_vars.inp_key_left = ((g_sys.input.direction & INPUT_DIRECTION_LEFT) != 0) || g_vars.inp_keyboard[0x4B] || g_vars.inp_keyboard[0x7A]; - 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 || 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]; + g_vars.inp_key_left = ((g_sys.input.direction & INPUT_DIRECTION_LEFT) != 0); + g_vars.inp_key_right = ((g_sys.input.direction & INPUT_DIRECTION_RIGHT) != 0); + g_vars.inp_key_up = ((g_sys.input.direction & INPUT_DIRECTION_UP) != 0); + g_vars.inp_key_down = ((g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0); + g_vars.inp_key_space = g_sys.input.space; + g_vars.inp_key_jump = g_sys.input.jump; } static void do_title_screen() { @@ -78,8 +78,8 @@ static void do_select_player() { 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 { + screen_clear_sprites(1); update_input(); const uint32_t timestamp = g_sys.get_timestamp(); switch (state) { @@ -205,11 +205,10 @@ static void do_select_player() { } continue; } - screen_flip(); + g_sys.update_screen(); screen_vsync(); const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp(); g_sys.sleep(diff < 10 ? 10 : diff); - screen_clear_sprites(); if (g_sys.input.space || g_vars.play_demo_flag) { quit = 1; } @@ -222,14 +221,14 @@ static void do_inter_screen_helper(int xpos, int ypos, int c) { if (c != 0) { screen_vsync(); } - screen_clear_sprites(); + screen_clear_sprites(1); } for (int i = 0; i < 40; ++i) { screen_add_sprite(xpos - 20 + 1 + i, ypos - 20 + 1 + i, 125); if (c != 0) { screen_vsync(); } - screen_clear_sprites(); + screen_clear_sprites(1); } } @@ -237,7 +236,7 @@ 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_res.amiga_data ? "inter.lbm" : "inter.sqz", GAME_SCREEN_W, g_options.cga_colors ? 9 : -1); - screen_clear_sprites(); + screen_clear_sprites(1); if (g_vars.level > 1) { for (int i = 0; i < g_vars.level - 1; ++i) { do_inter_screen_helper(xpos[i], ypos[i], 0); @@ -251,12 +250,12 @@ static void do_inter_screen() { do_inter_screen_helper(xpos[g_vars.level - 1], ypos[g_vars.level - 1], 1); } // screen_do_transition2(); - screen_flip(); + g_sys.update_screen(); if (g_vars.level < MAX_LEVELS - 1) { play_sound(SOUND_2); screen_add_sprite(xpos[g_vars.level], ypos[g_vars.level], 126); } - screen_flip(); + g_sys.update_screen(); const uint32_t timestamp = g_sys.get_timestamp() + 4 * 1000; do { update_input(); @@ -270,7 +269,6 @@ static void do_inter_screen() { void game_main() { play_music(0); screen_init(); - screen_flip(); g_vars.start_level = 0; if (g_res.amiga_data) { load_spr("sprite", g_res.spr_sqv, 0); diff --git a/bb/game.h b/bb/game.h index efc2ff6..88bdd02 100644 --- a/bb/game.h +++ b/bb/game.h @@ -152,15 +152,16 @@ struct vars_t { bool two_players_flag; bool switch_player_scrolling_flag; int music_num; - uint8_t inp_keyboard[256]; + bool inp_key_jump; + bool inp_key_jump_prev; bool inp_key_space; + bool inp_key_space_prev; bool inp_key_up; + bool inp_key_up_prev; bool inp_key_down; + bool inp_key_down_prev; bool inp_key_right; bool inp_key_left; - bool inp_key_up_prev; - bool inp_key_down_prev; - bool inp_key_space_prev; struct door_t doors[MAX_DOORS]; struct object_t objects[MAX_OBJECTS]; int vinyls_count; @@ -219,13 +220,12 @@ extern void level_call_object_func(struct object_t *); /* screen.c */ extern void screen_init(); -extern void screen_clear_sprites(); +extern void screen_clear_sprites(int pos_flag); extern void screen_add_sprite(int x, int y, int frame); 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 fh, int fw, int x, int y); -extern void screen_flip(); extern void screen_unk5(); extern void screen_do_transition1(int a); extern void screen_do_transition2(); diff --git a/bb/level.c b/bb/level.c index 44edd91..8665b17 100644 --- a/bb/level.c +++ b/bb/level.c @@ -1162,7 +1162,8 @@ void do_level_enter_door(struct object_t *obj) { if (g_vars.two_players_flag) { do_level_update_panel_2nd_player(); } - screen_flip(); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); + g_sys.update_screen(); screen_do_transition1(1); obj->unk3D = 0; obj->sprite_type = 0; @@ -1224,9 +1225,9 @@ static void do_level_update_input(struct object_t *obj) { obj->direction_lr |= OBJECT_DIRECTION_LEFT; } _si = triggers_get_tile_type(obj->xpos16, obj->ypos16); - if (g_vars.inp_key_up && !g_vars.inp_key_space) { + if ((g_options.jump_button ? g_vars.inp_key_jump : g_vars.inp_key_up) && !g_vars.inp_key_space) { obj->direction_ud = OBJECT_DIRECTION_UP; - if (!g_vars.inp_key_up_prev && obj->sprite_type != 0) { + if ((g_options.jump_button ? !g_vars.inp_key_jump_prev : !g_vars.inp_key_up_prev) && obj->sprite_type != 0) { obj->yfriction = 0; _di = triggers_get_tile_type(obj->xpos16, obj->ypos16 - 2); if (_di == 10 && (_si == 0 || _si == 1)) { @@ -1255,6 +1256,7 @@ static void do_level_update_input(struct object_t *obj) { } g_vars.inp_key_up_prev = g_vars.inp_key_up; g_vars.inp_key_down_prev = g_vars.inp_key_down; + g_vars.inp_key_jump_prev = g_vars.inp_key_jump; if (obj->grab_state == 0) { if (obj->carry_crate_flag != 0 && _si == 5) { // crate obj->grab_type = 0; @@ -1301,12 +1303,10 @@ static void do_level_update_scrolling(struct object_t *obj) { if ((g_vars.screen_scrolling_dirmask & 2) != 0 && obj->screen_xpos < TILEMAP_SCREEN_W / 2) { g_vars.screen_scrolling_dirmask &= ~2; g_vars.switch_player_scrolling_flag = 0; - g_vars.inp_keyboard[0xC1] = 0; } if ((g_vars.screen_scrolling_dirmask & 1) != 0 && obj->screen_xpos > TILEMAP_SCREEN_W / 2) { g_vars.screen_scrolling_dirmask &= ~1; g_vars.switch_player_scrolling_flag = 0; - g_vars.inp_keyboard[0xC1] = 0; } } else { int _si = (obj->xvelocity >> 3) + obj->unk1C; @@ -1871,18 +1871,6 @@ static void do_level_update_objects() { obj->direction_lr = 0; obj->direction_ud = 0; if (obj->type < 2) { - if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player - if (!g_vars.switch_player_scrolling_flag && g_vars.two_players_flag) { - if (!g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER1].scrolling_lock_flag) { - g_vars.player2_scrolling_flag = 1; - g_vars.switch_player_scrolling_flag = 1; - } else if (g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER2].scrolling_lock_flag) { - g_vars.player2_scrolling_flag = 1; - g_vars.switch_player_scrolling_flag = 1; - } - } - g_vars.inp_keyboard[0xC1] = 0; - } if (obj->blinking_counter != 0) { --obj->blinking_counter; } @@ -2099,7 +2087,7 @@ void do_level() { if (g_options.amiga_copper_bars) { g_sys.set_copper_bars(_copper_data + g_vars.level * 18); } - g_vars.inp_keyboard[0xB9] = 0; // SPACE + // g_vars.inp_keyboard[0xB9] = 0; // SPACE // g_vars.screen_draw_offset = TILEMAP_OFFSET_Y * 40; g_vars.update_objects_counter = 0; g_vars.game_over_flag = 0; @@ -2110,25 +2098,9 @@ void do_level() { g_sys.render_set_sprites_clipping_rect(0, TILEMAP_OFFSET_Y, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H); bool screen_transition_flag = true; do { + screen_clear_sprites(0); const uint32_t timestamp = g_sys.get_timestamp(); update_input(); - if (g_vars.inp_keyboard[0xBF] != 0) { // F5, quit game - play_sound(SOUND_0); - g_vars.inp_keyboard[0xBF] = 0; - g_vars.quit_level_flag = 1; - g_vars.play_level_flag = 0; - g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0; - g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0; - g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0; - g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0; - if (!g_vars.play_demo_flag) { - g_vars.start_level = 0; - } - } else if (g_vars.inp_keyboard[0xC4] != 0) { // F10 - play_sound(SOUND_0); - while (g_vars.inp_keyboard[0xC4] != 0 && g_vars.inp_keyboard[0xB] == 0); - while (g_vars.inp_keyboard[0xC4] != 0 && g_vars.inp_keyboard[0xB] != 0); - } // demo do_level_update_scrolling2(); do_level_update_objects(); @@ -2138,18 +2110,17 @@ void do_level() { ++g_vars.level_loop_counter; draw_level_panel(); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); if (screen_transition_flag) { screen_transition_flag = false; - g_sys.update_screen(g_res.vga, 0); screen_do_transition2(); } else { - g_sys.update_screen(g_res.vga, 1); + g_sys.update_screen(); } memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp(); g_sys.sleep(diff < 10 ? 10 : diff); - screen_clear_sprites(); } while (!g_sys.input.quit && !g_vars.quit_level_flag); // g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40; @@ -2158,5 +2129,4 @@ void do_level() { g_sys.set_copper_bars(0); } g_sys.render_set_sprites_clipping_rect(0, 0, GAME_SCREEN_W, GAME_SCREEN_H); - g_vars.inp_keyboard[0xBF] = 0; } diff --git a/bb/resource.c b/bb/resource.c index b544b69..56376ec 100644 --- a/bb/resource.c +++ b/bb/resource.c @@ -314,11 +314,11 @@ void load_img(const char *filename, int screen_w, int dither_pattern) { size = read_compressed_file(filename, g_res.tmp); } assert(size <= 32000); - load_iff(g_res.tmp, size, g_res.vga, screen_w, dither_pattern); + load_iff(g_res.tmp, size, g_res.vga, 320, dither_pattern); + g_sys.copy_bitmap(g_res.vga, 320, 200); if (dither_pattern < 0) { g_sys.set_screen_palette(g_res.palette, 0, 16, 8); } - g_sys.update_screen(g_res.vga, 0); } void load_m(const char *filename) { diff --git a/bb/screen.c b/bb/screen.c index f5c0363..2a906bc 100644 --- a/bb/screen.c +++ b/bb/screen.c @@ -8,15 +8,19 @@ #define MAX_SPRITESHEET_W 512 #define MAX_SPRITESHEET_H 512 -static int _offset_x, _offset_y; +static int _spr_pos_flag; + +static int _offset_x_center, _offset_y_bottom, _offset_y_center; void screen_init() { memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); - _offset_x = (GAME_SCREEN_W > 320) ? (GAME_SCREEN_W - 320) / 2 : 0; // center horizontally - _offset_y = (GAME_SCREEN_H > 200) ? (GAME_SCREEN_H - 200) : 0; // align to bottom + _offset_x_center = (GAME_SCREEN_W > 320) ? (GAME_SCREEN_W - 320) / 2 : 0; // center horizontally + _offset_y_center = (GAME_SCREEN_H > 200) ? (GAME_SCREEN_H - 200) / 2 : 0; // center vertically + _offset_y_bottom = (GAME_SCREEN_H > 200) ? (GAME_SCREEN_H - 200) : 0; // align to bottom } -void screen_clear_sprites() { +void screen_clear_sprites(int pos_flag) { + _spr_pos_flag = pos_flag; g_sys.render_clear_sprites(); } @@ -32,11 +36,6 @@ static void add_game_sprite(int x, int y, int frame, int xflip) { if (frame >= SPRITES_COUNT) { spr_type = RENDER_SPR_LEVEL; frame -= SPRITES_COUNT; - } else { - if (y >= 161 && frame >= 120) { - x += _offset_x; - y += _offset_y; - } } g_sys.render_add_sprite(spr_type, frame, x - w / 2, y - h, xflip); } @@ -60,6 +59,13 @@ void screen_add_sprite(int x, int y, int frame) { return; } } + if (_spr_pos_flag) { /* introduction screens */ + x += _offset_x_center; + y += _offset_y_center; + } else if ((frame >= 120 && frame < SPRITES_COUNT) && y >= 161) { /* bottom panel */ + x += _offset_x_center; + y += _offset_y_bottom; + } add_game_sprite(x, y, frame, 0); } @@ -82,9 +88,9 @@ void screen_vsync() { } void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y) { - x += _offset_x; + x += _offset_x_center; if (y == 161) { - y += _offset_y; + y += _offset_y_bottom; } y += fh + 2; if (g_options.amiga_status_bar || g_res.amiga_data) { @@ -104,10 +110,6 @@ void screen_draw_frame(const uint8_t *frame, int fh, int fw, int x, int y) { } } -void screen_flip() { - g_sys.update_screen(g_res.vga, 1); -} - void screen_unk5() { // screen_do_transition2(); screen_clear(0); @@ -183,8 +185,8 @@ static void draw_number_amiga(int digit, int x, int y) { void screen_draw_number(int num, int x, int y, int color) { if (y >= 161) { - x += _offset_x; - y += _offset_y; + x += _offset_x_center; + y += _offset_y_bottom; } y += TILEMAP_OFFSET_Y; if (g_options.amiga_status_bar || g_res.amiga_data) { diff --git a/intern.h b/intern.h index 6dc8b56..615502f 100644 --- a/intern.h +++ b/intern.h @@ -11,7 +11,7 @@ #include #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) -#define SWAP(x, y) do { typeof(x) tmp = x; x = y; y = tmp; } while(0) +#define SWAP(x, y) do { __typeof__(x) tmp = x; x = y; y = tmp; } while(0) #undef MIN static inline int MIN(int a, int b) { @@ -51,6 +51,7 @@ struct options_t { int screen_w; int screen_h; bool dos_scrolling; + bool jump_button; // 'bb' only options bool amiga_copper_bars; bool amiga_colors; @@ -62,7 +63,6 @@ struct options_t { struct game_t { const char *name; - //int (*detect)(const char *data_path); void (*run)(const char *data_path); }; diff --git a/ja/game.c b/ja/game.c index 2a87b34..4d478d7 100644 --- a/ja/game.c +++ b/ja/game.c @@ -15,6 +15,7 @@ void update_input() { g_vars.input_key_up = (g_sys.input.direction & INPUT_DIRECTION_UP) != 0 ? 0xFF : 0; g_vars.input_key_down = (g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0 ? 0xFF : 0; g_vars.input_key_space = g_sys.input.space ? 0xFF : 0; + g_vars.input_key_jump = g_sys.input.jump ? 0xFF : 0; g_vars.input_keystate[2] = g_sys.input.digit1; g_vars.input_keystate[3] = g_sys.input.digit2; @@ -52,7 +53,8 @@ static void scroll_screen_palette() { for (int i = 0; i < count; ++i) { g_sys.set_palette_color(225 + i, g_res.tmp + (225 + g_vars.level_time + i) * 3); } - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, 320, 200); + g_sys.update_screen(); } static void do_select_screen_scroll_palette(int start, int end, int step, int count) { @@ -66,7 +68,8 @@ static void do_select_screen_scroll_palette(int start, int end, int step, int co g_vars.palette_buffer[i] = color; } g_sys.set_screen_palette(g_vars.palette_buffer + start * 3, start, end - start + 1, 6); - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, 320, 200); + g_sys.update_screen(); g_sys.sleep(20); } while (--count != 0); } diff --git a/ja/game.h b/ja/game.h index 02965b9..548a9d3 100644 --- a/ja/game.h +++ b/ja/game.h @@ -129,7 +129,7 @@ struct vars_t { int player; bool input_keystate[128]; uint32_t timestamp; - uint8_t input_key_left, input_key_right, input_key_down, input_key_up, input_key_space; + uint8_t input_key_left, input_key_right, input_key_down, input_key_up, input_key_space, input_key_jump; uint16_t buffer[128 * 2]; /* level objects state 0xFFFF, 0xFF20 or g_vars.objects_table index */ int16_t dragon_coords[1 + 128]; struct player_t players_table[2]; diff --git a/ja/level.c b/ja/level.c index 1d0831b..c814095 100644 --- a/ja/level.c +++ b/ja/level.c @@ -27,7 +27,8 @@ static void do_end_of_level() { ja_decode_motif(g_vars.level_num % 9, color_index); static const uint8_t white[] = { 0x3F, 0x3F, 0x3F }; g_sys.set_palette_color(color_index, white); - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); + g_sys.update_screen(); g_sys.sleep(1000); g_sys.fade_out_palette(); } @@ -398,7 +399,7 @@ static void level_update_player_anim_1(struct player_t *player) { static void level_update_player_anim_5(struct player_t *player) { level_player_update_hdirection(player); player->obj.spr_num = 5; - if (player_jump_counter(&player->obj) != 0 && (player_flags2(&player->obj) & 1) == 0 && g_vars.input_key_up) { + if (player_jump_counter(&player->obj) != 0 && (player_flags2(&player->obj) & 1) == 0 && (g_options.jump_button ? g_vars.input_key_jump : g_vars.input_key_up)) { --player_jump_counter(&player->obj); const int dy = (int8_t)player_anim_dy[player_jump_counter(&player->obj)] + player_y_delta(&player->obj); if (dy >= -70) { @@ -550,7 +551,7 @@ static void level_update_player_anim_12(struct player_t *player) { static void level_update_player_anim_18(struct player_t *player) { level_player_update_hdirection(player); player->obj.spr_num = 18; - if (player_jump_counter(&player->obj) != 0 && g_vars.input_key_up) { + if (player_jump_counter(&player->obj) != 0 && (g_options.jump_button ? g_vars.input_key_jump : g_vars.input_key_up)) { --player_jump_counter(&player->obj); player_y_delta(&player->obj) += (int8_t)player_anim_dy[player_jump_counter(&player->obj)]; } @@ -594,7 +595,7 @@ static void level_update_player_anim_19(struct player_t *player) { static void level_update_player_anim_26(struct player_t *player) { level_player_update_hdirection(player); player->obj.spr_num = 26; - if (player_jump_counter(&player->obj) == 0 || !g_vars.input_key_up) { + if (player_jump_counter(&player->obj) == 0 || (g_options.jump_button ? !g_vars.input_key_jump : !g_vars.input_key_up)) { return; } --player_jump_counter(&player->obj); @@ -737,7 +738,7 @@ static void level_update_player_from_input(struct player_t *player) { } else { mask <<= 4; if ((player_flags(&player->obj) & 0x10) == 0) { - mask |= (g_vars.input_key_up & 8); + mask |= (g_options.jump_button ? g_vars.input_key_jump : g_vars.input_key_up) & 8; } mask |= (g_vars.input_key_right & 4); if (player_jump_counter(&player->obj) == 7) { @@ -2695,7 +2696,8 @@ static void level_sync() { --g_vars.level_time; } } - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); + g_sys.update_screen(); g_sys.render_clear_sprites(); const int diff = (g_vars.timestamp + (1000 / 30)) - g_sys.get_timestamp(); g_sys.sleep(MAX(diff, 10)); diff --git a/ja/screen.c b/ja/screen.c index 025f097..bf5170d 100644 --- a/ja/screen.c +++ b/ja/screen.c @@ -46,17 +46,8 @@ void video_copy_vga(int size) { } else { assert(size == 0x7D00); g_sys.set_screen_palette(g_res.tmp, 0, 256, 6); - const uint8_t *src = g_res.tmp + 768; - if (GAME_SCREEN_W * GAME_SCREEN_H == 64000) { - memcpy(g_res.vga, src, 64000); - } else { - memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H); - for (int y = 0; y < MIN(200, GAME_SCREEN_H); ++y) { - memcpy(g_res.vga + y * GAME_SCREEN_W, src, MIN(320, GAME_SCREEN_W)); - src += 320; - } - } - g_sys.update_screen(g_res.vga, 0); + memcpy(g_res.vga, g_res.tmp + 768, 64000); + g_sys.copy_bitmap(g_res.vga, 320, 200); } } diff --git a/ja/unpack.c b/ja/unpack.c index 67c51be..ff83528 100644 --- a/ja/unpack.c +++ b/ja/unpack.c @@ -1,5 +1,5 @@ -/* uncompress data packed with DIET by T.Matsumoto */ +/* uncompress data packed with DIET.EXE */ #include "unpack.h" #include "util.h" diff --git a/main.c b/main.c index 688b537..79aad22 100644 --- a/main.c +++ b/main.c @@ -28,43 +28,40 @@ static const char *USAGE = ; static struct game_t *detect_game(const char *data_path) { -#if 0 - extern struct game_t bb_game; - extern struct game_t ja_game; - extern struct game_t p2_game; - static struct game_t *games[] = { - &bb_game, - &ja_game, - &p2_game, - 0 - }; - for (int i = 0; games[i]; ++i) { - if (games[i]->detect(data_path)) { - return games[i]; - } - } - return 0; -#else extern struct game_t game; return &game; -#endif } +#if defined(PSP) +/* stubs */ +void sound_init() { +} +void sound_fini() { +} +void play_sound(int num) { +} +void play_music(int num) { +} +#endif + int main(int argc, char *argv[]) { - g_options.start_xpos16 = -1; - g_options.start_ypos16 = -1; - g_options.screen_w = 320; - g_options.screen_h = 200; - g_options.dos_scrolling = false; - g_options.amiga_copper_bars = true; - g_options.amiga_colors = true; - // g_options.amiga_status_bar = true; - g_options.cga_colors = false; - g_options.hybrid_color = false; const char *data_path = DEFAULT_DATA_PATH; int scale_factor = DEFAULT_SCALE_FACTOR; const char *scale_filter = DEFAULT_SCALE_FILTER; bool fullscreen = false; + g_options.start_xpos16 = -1; + g_options.start_ypos16 = -1; + g_options.amiga_copper_bars = true; + g_options.amiga_colors = true; + // g_options.amiga_status_bar = true; +#if defined(PSP) + g_options.screen_w = 480; + g_options.screen_h = 272; + g_options.jump_button = true; +#else + g_options.screen_w = 320; + g_options.screen_h = 200; + // g_options.jump_button = true; if (argc == 2) { struct stat st; if (stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode)) { @@ -121,7 +118,14 @@ int main(int argc, char *argv[]) { if (sscanf(optarg, "%dx%d", &g_options.screen_w, &g_options.screen_h) == 2) { // align to tile 16x16 g_options.screen_w = (g_options.screen_w + 15) & ~15; - g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40; // PANEL_H + g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40; // PANEL_H; + // do not allow lower resolution than the original + if (g_options.screen_w < 320) { + g_options.screen_w = 320; + } + if (g_options.screen_h < 200) { + g_options.screen_h = 200; + } } break; case 10: @@ -138,6 +142,7 @@ int main(int argc, char *argv[]) { return -1; } } +#endif struct game_t *game = detect_game(data_path); if (!game) { fprintf(stdout, "No data files found\n"); diff --git a/p2/game.c b/p2/game.c index 7f487ce..63735ff 100644 --- a/p2/game.c +++ b/p2/game.c @@ -15,6 +15,7 @@ void update_input() { g_vars.input.key_up = (g_sys.input.direction & INPUT_DIRECTION_UP) != 0 ? 0xFF : 0; g_vars.input.key_down = (g_sys.input.direction & INPUT_DIRECTION_DOWN) != 0 ? 0xFF : 0; g_vars.input.key_space = g_sys.input.space ? 0xFF : 0; + g_vars.input.key_jump = g_sys.input.jump ? 0xFF : 0; g_vars.input.keystate[2] = g_sys.input.digit1; g_vars.input.keystate[3] = g_sys.input.digit2; @@ -51,7 +52,8 @@ static void do_programmed_in_1992_screen() { video_draw_string(offset, 1, "PROGRAMMED IN 1992 ON AT >286 12MHZ>"); offset += 0x1E0; video_draw_string(offset, 3, "> > > ENJOY OLDIES<<"); - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, 320, 200); + g_sys.update_screen(); wait_input(100); video_clear(); } @@ -76,23 +78,14 @@ static void do_credits() { video_draw_string(offset, 2, "CRISTELLE> GIL ESPECHE AND CORINNE>"); offset += 0x1E0; video_draw_string(offset, 0, "SEBASTIEN BECHET AND OLIVIER AKA DELTA>"); - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, 320, 200); + g_sys.update_screen(); } static void update_screen_img(const uint8_t *src, int present) { - const int size = GAME_SCREEN_W * GAME_SCREEN_H; - if (size < 64000) { - return; - } else if (size == 64000) { - g_sys.update_screen(src, present); - } else { - memset(g_res.vga, 0, size); - const int y_offs = (GAME_SCREEN_H - 200) / 2; - const int x_offs = (GAME_SCREEN_W - 320) / 2; - for (int y = 0; y < 200; ++y) { - memcpy(g_res.vga + (y_offs + y) * GAME_SCREEN_W + x_offs, src + y * 320, 320); - } - g_sys.update_screen(g_res.vga, present); + g_sys.copy_bitmap(src, 320, 200); + if (present) { + g_sys.update_screen(); } } @@ -190,8 +183,8 @@ void do_gameover_screen() { if (data) { video_copy_img(data); video_copy_background(); - g_sys.update_screen(g_res.vga, 0); g_sys.set_screen_palette(gameover_palette_data, 0, 16, 6); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); do_gameover_animation(); g_sys.fade_out_palette(); free(data); @@ -205,8 +198,8 @@ static void do_menu2() { if (data) { video_copy_img(data); video_copy_background(); - g_sys.update_screen(g_res.vga, 0); g_sys.set_screen_palette(data + 32000, 0, 16, 6); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); g_sys.fade_in_palette(); do_demo_animation(); g_sys.fade_out_palette(); diff --git a/p2/game.h b/p2/game.h index d736967..9b1430c 100644 --- a/p2/game.h +++ b/p2/game.h @@ -120,7 +120,7 @@ struct vars_t { } random; struct { bool keystate[128]; - uint8_t key_left, key_right, key_down, key_up, key_space; + uint8_t key_left, key_right, key_down, key_up, key_space, key_jump; uint8_t key_vdir, key_hdir; uint16_t demo_offset; uint8_t demo_mask, demo_counter; diff --git a/p2/level.c b/p2/level.c index 69c7be7..1bfb954 100644 --- a/p2/level.c +++ b/p2/level.c @@ -2446,7 +2446,7 @@ static void level_update_player() { mask <<= 1; mask |= g_vars.input.key_left & 1; mask <<= 1; - mask |= g_vars.input.key_up & 1; + mask |= (g_options.jump_button ? g_vars.input.key_jump : g_vars.input.key_up) & 1; mask <<= 1; mask |= g_vars.input.key_down & 1; mask <<= 1; @@ -2664,7 +2664,7 @@ static void level_update_player_collision() { level_add_object75_score(obj_player, (int16_t)data[num >> 1]); } } - g_vars.objects_tbl[1].data.p.y_velocity = (g_vars.input.key_up != 0) ? -224 : -64; + g_vars.objects_tbl[1].data.p.y_velocity = (g_options.jump_button ? g_vars.input.key_jump : g_vars.input.key_up) ? -224 : -64; g_vars.player_jumping_counter = 0; g_vars.objects_tbl[1].y_pos -= g_vars.monster.collide_y_dist; } else if (g_vars.objects_tbl[1].data.p.y_velocity <= 32) { @@ -3269,7 +3269,8 @@ static void level_update_light_palette() { static void level_sync() { update_input(); - g_sys.update_screen(g_res.vga, 1); + g_sys.copy_bitmap(g_res.vga, GAME_SCREEN_W, GAME_SCREEN_H); + g_sys.update_screen(); g_sys.render_clear_sprites(); const int diff = (g_vars.timestamp + (1000 / 30)) - g_sys.get_timestamp(); g_sys.sleep(MAX(diff, 10)); diff --git a/p2/screen.c b/p2/screen.c index e294f3b..7c91b53 100644 --- a/p2/screen.c +++ b/p2/screen.c @@ -61,9 +61,7 @@ static void convert_planar_tile_4bpp(const uint8_t *src, uint8_t *dst, int dst_p void video_draw_string(int offset, int hspace, const char *s) { offset += hspace; - const int y = (offset * 8) / 320 + (GAME_SCREEN_H - 200) / 2; - const int x = (offset * 8) % 320 + (GAME_SCREEN_W - 320) / 2; - uint8_t *dst = g_res.vga + y * GAME_SCREEN_W + x; + uint8_t *dst = g_res.vga + offset * 8; while (*s) { uint8_t code = *s++; if (code != 0x20) { @@ -71,7 +69,7 @@ void video_draw_string(int offset, int hspace, const char *s) { if (code > 9) { code -= 2; } - decode_planar(g_res.allfonts + code * 48, dst, GAME_SCREEN_W, 8, 12, 0); + decode_planar(g_res.allfonts + code * 48, dst, 320, 8, 12, 0); } dst += 8; } diff --git a/sys.h b/sys.h index a3544af..b6c210c 100644 --- a/sys.h +++ b/sys.h @@ -14,11 +14,13 @@ #define RENDER_SPR_GAME 0 /* player sprites */ #define RENDER_SPR_LEVEL 1 /* level sprites */ #define RENDER_SPR_FG 2 /* foreground tiles */ +#define RENDER_SPR_COUNT 3 struct input_t { uint8_t direction; bool quit; bool space; + bool jump; bool digit1, digit2, digit3; }; @@ -36,7 +38,7 @@ enum sys_transition_e { struct sys_t { struct input_t input; - int (*init)(); + void (*init)(); void (*fini)(); void (*set_screen_size)(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen); void (*set_screen_palette)(const uint8_t *colors, int offset, int count, int depth); @@ -45,7 +47,8 @@ struct sys_t { void (*set_palette_color)(int i, const uint8_t *colors); void (*fade_in_palette)(); void (*fade_out_palette)(); - void (*update_screen)(const uint8_t *p, int present); + void (*copy_bitmap)(const uint8_t *p, int w, int h); + void (*update_screen)(); void (*shake_screen)(int dx, int dy); void (*transition_screen)(enum sys_transition_e type, bool open); void (*process_events)(); @@ -60,6 +63,7 @@ struct sys_t { void (*render_add_sprite)(int spr_type, int frame, int x, int y, int xflip); void (*render_clear_sprites)(); void (*render_set_sprites_clipping_rect)(int x, int y, int w, int h); + void (*print_log)(FILE *fp, const char *s); }; extern struct sys_t g_sys; diff --git a/sys_psp.c b/sys_psp.c new file mode 100644 index 0000000..da99daf --- /dev/null +++ b/sys_psp.c @@ -0,0 +1,428 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sys.h" + +PSP_MODULE_INFO("Blues Brothers", 0, 1, 0); +PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER); + +static uint32_t _buttons; + +static sys_audio_cb _audio_proc; +static void *_audio_param; +static int _audio_channel; +static SceUID _audio_mutex; + +static uint32_t _fb_offset; + +// static const int AUDIO_FREQ = 44100; +static const int AUDIO_SAMPLES_COUNT = 2048; + +static const int SCREEN_W = 480; +static const int SCREEN_H = 272; +static const int SCREEN_PITCH = 512; + +static uint32_t __attribute__((aligned(16))) _dlist[262144]; +static uint32_t __attribute__((aligned(16))) _clut[256]; + +#define MAX_SPRITES 256 + +struct vertex_t { + int16_t u, v; + int16_t x, y, z; +}; + +struct spritetexture_t { + int w, h; + uint8_t *bitmap; + int count; + struct sys_rect_t *r; +}; + +static struct spritetexture_t _spritetextures[RENDER_SPR_COUNT]; + +struct sprite_t { + struct vertex_t v[2]; + int tex; +}; + +static struct sprite_t _sprites[MAX_SPRITES]; +static int _sprites_count; + +static void print_log(FILE *fp, const char *s) { + static bool first_open = false; + if (!first_open) { + fp = fopen("stdout.txt", "w"); + first_open = true; + } else { + fp = fopen("stdout.txt", "a"); + } + fprintf(fp, "%s\n", s); + fclose(fp); +} + +static int exit_callback(int arg1, int arg2, void *common) { + g_sys.input.quit = true; + return 0; +} + +static int callback_thread(SceSize args, void *argp) { + const int cb = sceKernelCreateCallback("Exit Callback", exit_callback, NULL); + sceKernelRegisterExitCallback(cb); + sceKernelSleepThreadCB(); + return 0; +} + +static void psp_init() { + _buttons = 0; + + memset(&_audio_proc, 0, sizeof(_audio_proc)); + _audio_channel = -1; + _audio_mutex = 0; + + const int th = sceKernelCreateThread("update_thread", callback_thread, 0x11, 0xFA0, 0, 0); + if (th >= 0) { + sceKernelStartThread(th, 0, 0); + } + + sceKernelDcacheWritebackAll(); + + sceCtrlSetSamplingCycle(0); + sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); +} + +static void psp_fini() { + sceGuTerm(); + sceKernelExitGame(); +} + +static void psp_set_screen_size(int w, int h, const char *caption, int scale, const char *filter, bool fullscreen) { + sceGuInit(); + sceGuStart(GU_DIRECT, _dlist); + + const int fbSize = SCREEN_PITCH * SCREEN_H * sizeof(uint32_t); // rgba + uint32_t vramOffset = 0; + sceGuDrawBuffer(GU_PSM_8888, (void *)vramOffset, SCREEN_PITCH); vramOffset += fbSize; + sceGuDispBuffer(SCREEN_W, SCREEN_H, (void *)vramOffset, SCREEN_PITCH); vramOffset += fbSize; + + sceGuOffset(2048 - (SCREEN_W / 2), 2048 - (SCREEN_H / 2)); + sceGuViewport(2048, 2048, SCREEN_W, SCREEN_H); + sceGuScissor(0, 0, SCREEN_W, SCREEN_H); + sceGuEnable(GU_SCISSOR_TEST); + sceGuEnable(GU_TEXTURE_2D); + sceGuDisable(GU_DEPTH_TEST); + + sceGuClearColor(0); + sceGuClear(GU_COLOR_BUFFER_BIT); + + sceGuFinish(); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); + + sceDisplayWaitVblankStart(); + _fb_offset = (uint32_t)sceGuSwapBuffers(); + sceGuDisplay(GU_TRUE); + + for (int i = 0; i < 256; ++i) { + _clut[i] = GU_RGBA(0, 0, 0, 255); + } + sceKernelDcacheWritebackRange(_clut, sizeof(_clut)); +} + +static void psp_set_screen_palette(const uint8_t *colors, int offset, int count, int depth) { + const int shift = 8 - depth; + for (int i = 0; i < count; ++i) { + int r = *colors++; + int g = *colors++; + int b = *colors++; + if (shift != 0) { + r = (r << shift) | (r >> (depth - shift)); + g = (g << shift) | (g >> (depth - shift)); + b = (b << shift) | (b >> (depth - shift)); + } + _clut[offset + i] = GU_RGBA(r, g, b, 255); + } + sceKernelDcacheWritebackRange(_clut, sizeof(_clut)); +} + +static uint32_t convert_amiga_color(uint16_t color) { + uint8_t r = (color >> 8) & 15; + r |= r << 4; + uint8_t g = (color >> 4) & 15; + g |= g << 4; + uint8_t b = color & 15; + b |= b << 4; + return GU_RGBA(r, g, b, 255); +} + +static void psp_set_palette_amiga(const uint16_t *colors, int offset) { + for (int i = 0; i < 16; ++i) { + _clut[offset + i] = convert_amiga_color(colors[i]); + } + sceKernelDcacheWritebackRange(_clut, sizeof(_clut)); +} + +static void psp_set_copper_bars(const uint16_t *data) { +} + +static void psp_set_palette_color(int i, const uint8_t *colors) { + _clut[i] = GU_RGBA(colors[0], colors[1], colors[2], 255); + sceKernelDcacheWritebackRange(_clut, sizeof(_clut)); +} + +static void psp_fade_in_palette() { + sceDisplayWaitVblankStart(); + _fb_offset = (uint32_t)sceGuSwapBuffers(); +} + +static void psp_fade_out_palette() { + uint32_t *buffer = (uint32_t *)(((uint8_t *)sceGeEdramGetAddr()) + _fb_offset); + for (int y = 0; y < SCREEN_H; ++y) { + memset(buffer, 0, SCREEN_W * sizeof(uint32_t)); + buffer += SCREEN_PITCH; + } +} + +static void psp_transition_screen(enum sys_transition_e type, bool open) { +} + +static void psp_copy_bitmap(const uint8_t *p, int w, int h) { + const int dx = (SCREEN_W - w) / 2; + const int dy = (SCREEN_H - h) / 2; + uint32_t *buffer = (uint32_t *)(((uint8_t *)sceGeEdramGetAddr()) + _fb_offset); + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + buffer[(dy + y) * SCREEN_PITCH + (dx + x)] = _clut[*p++]; + } + } +} + +static void psp_update_screen() { + sceGuStart(GU_DIRECT, _dlist); + + sceGuClutMode(GU_PSM_8888, 0, 0xFF, 0); + sceGuClutLoad(256 / 8, _clut); + sceGuTexMode(GU_PSM_T8, 0, 0, 0); + sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGB); + sceGuTexFilter(GU_NEAREST, GU_NEAREST); + + sceGuEnable(GU_COLOR_TEST); + sceGuColorFunc(GU_NOTEQUAL, _clut[0], 0xFFFFFF); + + int prev_tex = -1; + + for (int i = 0; i < _sprites_count; ++i) { + struct sprite_t *spr = &_sprites[i]; + + if (prev_tex != spr->tex) { + struct spritetexture_t *st = &_spritetextures[spr->tex]; + sceGuTexImage(0, st->w, st->h, st->w, st->bitmap); + prev_tex = spr->tex; + } + + struct vertex_t *v = (struct vertex_t *)sceGuGetMemory(2 * sizeof(struct vertex_t)); + v[0] = spr->v[0]; + v[1] = spr->v[1]; + + sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, v); + } + + sceGuDisable(GU_COLOR_TEST); + + sceGuFinish(); + sceGuSync(GU_SYNC_WHAT_DONE, GU_SYNC_FINISH); + + sceDisplayWaitVblankStart(); + _fb_offset = (uint32_t)sceGuSwapBuffers(); +} + +static void psp_shake_screen(int dx, int dy) { + sceGuOffset(2048 - (SCREEN_W / 2) + dx, 2048 - (SCREEN_H / 2) + dy); +} + +static void psp_process_events() { + + g_sys.input.direction = 0; + + static const struct { + int psp; + int sys; + } mapping[] = { + { PSP_CTRL_UP, INPUT_DIRECTION_UP }, + { PSP_CTRL_RIGHT, INPUT_DIRECTION_RIGHT }, + { PSP_CTRL_DOWN, INPUT_DIRECTION_DOWN }, + { PSP_CTRL_LEFT, INPUT_DIRECTION_LEFT }, + { 0, 0 } + }; + SceCtrlData data; + sceCtrlPeekBufferPositive(&data, 1); + for (int i = 0; mapping[i].psp != 0; ++i) { + if (data.Buttons & mapping[i].psp) { + g_sys.input.direction |= mapping[i].sys; + } + } + static const int lxMargin = 64; + if (data.Lx < 127 - lxMargin) { + g_sys.input.direction |= INPUT_DIRECTION_LEFT; + } else if (data.Lx > 127 + lxMargin) { + g_sys.input.direction |= INPUT_DIRECTION_RIGHT; + } + static const int lyMargin = 64; + if (data.Ly < 127 - lyMargin) { + g_sys.input.direction |= INPUT_DIRECTION_UP; + } else if (data.Ly > 127 + lyMargin) { + g_sys.input.direction |= INPUT_DIRECTION_DOWN; + } + + // PSP_CTRL_CROSS + g_sys.input.space = (data.Buttons & PSP_CTRL_SQUARE) != 0; + g_sys.input.jump = (data.Buttons & PSP_CTRL_CIRCLE) != 0; + // PSP_CTRL_TRIANGLE + + const uint32_t mask = data.Buttons ^ _buttons; + if ((data.Buttons & PSP_CTRL_LTRIGGER) & mask) { + } + if ((data.Buttons & PSP_CTRL_RTRIGGER) & mask) { + } + _buttons = data.Buttons; +} + +static void psp_sleep(int duration) { + sceKernelDelayThread(duration * 1000); +} + +static uint32_t psp_get_timestamp() { + struct timeval tv; + sceKernelLibcGettimeofday(&tv, 0); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void psp_lock_audio() { + sceKernelWaitSema(_audio_mutex, 1, 0); +} + +static void psp_unlock_audio() { + sceKernelSignalSema(_audio_mutex, 1); +} + +static void audio_callback(void *buf, unsigned int samples, void *param) { // 44100hz S16 stereo + int16_t buf22khz[samples]; + memset(buf22khz, 0, sizeof(buf22khz)); + psp_lock_audio(); + _audio_proc(_audio_param, (uint8_t *)buf22khz, samples); + psp_unlock_audio(); + uint32_t *buf44khz = (uint32_t *)buf; + static int16_t prev; + for (unsigned int i = 0; i < samples; ++i) { + const int16_t current = buf22khz[i]; + buf44khz[i] = (current << 16) | (((prev + current) >> 1) & 0xFFFF); + prev = current; + } +} + +static void psp_start_audio(sys_audio_cb callback, void *param) { + // sceAudioSetFrequency(AUDIO_FREQ); + pspAudioInit(); + _audio_proc = callback; + _audio_param = param; + _audio_mutex = sceKernelCreateSema("audio_lock", 0, 1, 1, 0); + _audio_channel = sceAudioChReserve(PSP_AUDIO_NEXT_CHANNEL, AUDIO_SAMPLES_COUNT, PSP_AUDIO_FORMAT_STEREO); + pspAudioSetChannelCallback(_audio_channel, audio_callback, 0); +} + +static void psp_stop_audio() { + sceAudioChRelease(_audio_channel); + sceKernelDeleteSema(_audio_mutex); + pspAudioEnd(); +} + +static void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h, uint8_t color_key, bool update_pal) { + struct spritetexture_t *st = &_spritetextures[spr_type]; + st->r = (struct sys_rect_t *)malloc(count * sizeof(struct sys_rect_t)); + if (st->r) { + memcpy(st->r, r, count * sizeof(struct sys_rect_t)); + st->count = count; + } + st->bitmap = (uint8_t *)memalign(16, w * h); + if (st->bitmap) { + memcpy(st->bitmap, data, w * h); + st->w = w; + st->h = h; + sceKernelDcacheWritebackRange(st->bitmap, w * h); + } +} + +static void render_unload_sprites(int spr_type) { + struct spritetexture_t *st = &_spritetextures[spr_type]; + if (st->r) { + free(st->r); + } + if (st->bitmap) { + free(st->bitmap); + } + memset(st, 0, sizeof(struct spritetexture_t)); +} + +static void render_add_sprite(int spr_type, int frame, int x, int y, int xflip) { + if (_sprites_count < MAX_SPRITES) { + struct sprite_t *spr = &_sprites[_sprites_count]; + struct vertex_t *v = spr->v; + + struct sys_rect_t *r = &_spritetextures[spr_type].r[frame]; + if (!xflip) { + v[0].u = r->x; v[1].u = r->x + r->w; + } else { + v[0].u = r->x + r->w; v[1].u = r->x; + } + v[0].v = r->y; v[1].v = r->y + r->h; + v[0].x = x; v[1].x = x + r->w; + v[0].y = y; v[1].y = y + r->h; + v[0].z = 0; v[1].z = 0; + + spr->tex = spr_type; + + ++_sprites_count; + } +} + +static void render_clear_sprites() { + _sprites_count = 0; +} + +static void render_set_sprites_clipping_rect(int x, int y, int w, int h) { + sceGuScissor(x, y, w, h); +} + +struct sys_t g_sys = { + .init = psp_init, + .fini = psp_fini, + .set_screen_size = psp_set_screen_size, + .set_screen_palette = psp_set_screen_palette, + .set_palette_amiga = psp_set_palette_amiga, + .set_copper_bars = psp_set_copper_bars, + .set_palette_color = psp_set_palette_color, + .fade_in_palette = psp_fade_in_palette, + .fade_out_palette = psp_fade_out_palette, + .copy_bitmap = psp_copy_bitmap, + .update_screen = psp_update_screen, + .shake_screen = psp_shake_screen, + .transition_screen = psp_transition_screen, + .process_events = psp_process_events, + .sleep = psp_sleep, + .get_timestamp = psp_get_timestamp, + .start_audio = psp_start_audio, + .stop_audio = psp_stop_audio, + .lock_audio = psp_lock_audio, + .unlock_audio = psp_unlock_audio, + .render_load_sprites = render_load_sprites, + .render_unload_sprites = render_unload_sprites, + .render_add_sprite = render_add_sprite, + .render_clear_sprites = render_clear_sprites, + .render_set_sprites_clipping_rect = render_set_sprites_clipping_rect, + .print_log = print_log, +}; diff --git a/sys_sdl2.c b/sys_sdl2.c index 16300d2..984864a 100644 --- a/sys_sdl2.c +++ b/sys_sdl2.c @@ -5,7 +5,6 @@ #define COPPER_BARS_H 80 #define MAX_SPRITES 256 -#define MAX_SPRITESHEETS 3 static const int FADE_STEPS = 16; @@ -16,7 +15,7 @@ struct spritesheet_t { SDL_Texture *texture; }; -static struct spritesheet_t _spritesheets[MAX_SPRITESHEETS]; +static struct spritesheet_t _spritesheets[RENDER_SPR_COUNT]; struct sprite_t { int sheet; @@ -44,7 +43,7 @@ static uint32_t _copper_palette[COPPER_BARS_H]; static SDL_GameController *_controller; static SDL_Joystick *_joystick; -static int sdl2_init() { +static void sdl2_init() { SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER); SDL_ShowCursor(SDL_DISABLE); _screen_w = _screen_h = 0; @@ -72,7 +71,6 @@ static int sdl2_init() { } } } - return 0; } static void sdl2_fini() { @@ -188,9 +186,9 @@ static void sdl2_set_screen_palette(const uint8_t *colors, int offset, int count SDL_Color *palette_colors = &_palette->colors[offset]; const int shift = 8 - depth; for (int i = 0; i < count; ++i) { - int r = colors[0]; - int g = colors[1]; - int b = colors[2]; + int r = *colors++; + int g = *colors++; + int b = *colors++; if (depth != 8) { r = (r << shift) | (r >> (depth - shift)); g = (g << shift) | (g >> (depth - shift)); @@ -200,7 +198,6 @@ static void sdl2_set_screen_palette(const uint8_t *colors, int offset, int count palette_colors[i].r = r; palette_colors[i].g = g; palette_colors[i].b = b; - colors += 3; } for (int i = 0; i < ARRAYSIZE(_spritesheets); ++i) { struct spritesheet_t *sheet = &_spritesheets[i]; @@ -286,11 +283,21 @@ static void sdl2_transition_screen(enum sys_transition_e type, bool open) { } while (r.x > 0 && (type == TRANSITION_CURTAIN || r.y > 0)); } -static void sdl2_update_screen(const uint8_t *p, int present) { - if (_copper_color_key != -1) { +static void sdl2_copy_bitmap(const uint8_t *p, int w, int h) { + if (w != _screen_w || h != _screen_h) { + memset(_screen_buffer, 0, _screen_w * _screen_h * sizeof(uint32_t)); + const int offset_x = (_screen_w - w) / 2; + const int offset_y = (_screen_h - h) / 2; + for (int j = 0; j < h; ++j) { + for (int i = 0; i < w; ++i) { + _screen_buffer[(offset_y + j) * _screen_w + (offset_x + i)] = _screen_palette[*p++]; + } + } + } else if (_copper_color_key != -1) { for (int j = 0; j < _screen_h; ++j) { - if (j / 2 < COPPER_BARS_H) { - const uint32_t line_color = _copper_palette[j / 2]; + const int color = (j * 200 / _screen_h) / 2; + if (color < COPPER_BARS_H) { + const uint32_t line_color = _copper_palette[color]; for (int i = 0; i < _screen_w; ++i) { _screen_buffer[j * _screen_w + i] = (p[i] == _copper_color_key) ? line_color : _screen_palette[p[i]]; } @@ -307,38 +314,39 @@ static void sdl2_update_screen(const uint8_t *p, int present) { } } SDL_UpdateTexture(_texture, 0, _screen_buffer, _screen_w * sizeof(uint32_t)); - if (present) { - SDL_Rect r; - r.x = _shake_dx; - r.y = _shake_dy; - r.w = _screen_w; - r.h = _screen_h; - SDL_RenderClear(_renderer); - SDL_RenderCopy(_renderer, _texture, 0, &r); +} - // sprites - SDL_RenderSetClipRect(_renderer, &_sprites_cliprect); - for (int i = 0; i < _sprites_count; ++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 + _shake_dx; - r.y = spr->y + _shake_dy; - r.w = sheet->r[spr->num].w; - r.h = sheet->r[spr->num].h; - 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); - } +static void sdl2_update_screen() { + SDL_Rect r; + r.x = _shake_dx; + r.y = _shake_dy; + r.w = _screen_w; + r.h = _screen_h; + SDL_RenderClear(_renderer); + SDL_RenderCopy(_renderer, _texture, 0, &r); + + // sprites + SDL_RenderSetClipRect(_renderer, &_sprites_cliprect); + for (int i = 0; i < _sprites_count; ++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 + _shake_dx; + r.y = spr->y + _shake_dy; + r.w = sheet->r[spr->num].w; + r.h = sheet->r[spr->num].h; + 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_RenderSetClipRect(_renderer, 0); - - SDL_RenderPresent(_renderer); } + SDL_RenderSetClipRect(_renderer, 0); + + SDL_RenderPresent(_renderer); } static void sdl2_shake_screen(int dx, int dy) { @@ -380,6 +388,10 @@ static void handle_keyevent(int keysym, bool keydown, struct input_t *input, boo case SDLK_SPACE: input->space = keydown; break; + case SDLK_LSHIFT: + case SDLK_RSHIFT: + input->jump = keydown; + break; case SDLK_ESCAPE: if (keydown) { g_sys.input.quit = true; @@ -437,13 +449,10 @@ static void handle_controlleraxis(int axis, int value, struct input_t *input) { static void handle_controllerbutton(int button, bool pressed, struct input_t *input, bool *paused) { switch (button) { case SDL_CONTROLLER_BUTTON_A: - case SDL_CONTROLLER_BUTTON_B: - case SDL_CONTROLLER_BUTTON_X: - case SDL_CONTROLLER_BUTTON_Y: input->space = pressed; break; - case SDL_CONTROLLER_BUTTON_BACK: - g_sys.input.quit = true; + case SDL_CONTROLLER_BUTTON_B: + input->jump = pressed; break; case SDL_CONTROLLER_BUTTON_START: if (!pressed) { @@ -520,8 +529,13 @@ static void handle_joystickaxismotion(int axis, int value, struct input_t *input } static void handle_joystickbutton(int button, int pressed, struct input_t *input) { - if (button == 0) { + switch (button) { + case 0: input->space = pressed; + break; + case 1: + input->jump = pressed; + break; } } @@ -717,6 +731,9 @@ static void render_set_sprites_clipping_rect(int x, int y, int w, int h) { _sprites_cliprect.h = h; } +static void print_log(FILE *fp, const char *s) { +} + struct sys_t g_sys = { .init = sdl2_init, .fini = sdl2_fini, @@ -727,6 +744,7 @@ struct sys_t g_sys = { .set_palette_color = sdl2_set_palette_color, .fade_in_palette = sdl2_fade_in_palette, .fade_out_palette = sdl2_fade_out_palette, + .copy_bitmap = sdl2_copy_bitmap, .update_screen = sdl2_update_screen, .shake_screen = sdl2_shake_screen, .transition_screen = sdl2_transition_screen, @@ -741,5 +759,6 @@ struct sys_t g_sys = { .render_unload_sprites = render_unload_sprites, .render_add_sprite = render_add_sprite, .render_clear_sprites = render_clear_sprites, - .render_set_sprites_clipping_rect = render_set_sprites_clipping_rect + .render_set_sprites_clipping_rect = render_set_sprites_clipping_rect, + .print_log = print_log, }; diff --git a/util.c b/util.c index 509ba5c..276f4ff 100644 --- a/util.c +++ b/util.c @@ -1,6 +1,8 @@ #include #include +#include +#include "sys.h" #include "util.h" int g_debug_mask = 0; @@ -21,6 +23,7 @@ void string_upper(char *p) { } } +#ifndef NDEBUG void print_debug(int debug_channel, const char *msg, ...) { if (g_debug_mask & debug_channel) { char buf[256]; @@ -29,8 +32,10 @@ void print_debug(int debug_channel, const char *msg, ...) { vsprintf(buf, msg, va); va_end(va); fprintf(stdout, "%s\n", buf); + g_sys.print_log(stdout, buf); } } +#endif void print_warning(const char *msg, ...) { char buf[256]; @@ -39,6 +44,7 @@ void print_warning(const char *msg, ...) { vsprintf(buf, msg, va); va_end(va); fprintf(stderr, "WARNING: %s\n", buf); + g_sys.print_log(stderr, buf); } void print_error(const char *msg, ...) { @@ -48,6 +54,7 @@ void print_error(const char *msg, ...) { vsprintf(buf, msg, va); va_end(va); fprintf(stderr, "ERROR: %s!\n", buf); + g_sys.print_log(stderr, buf); exit(-1); } @@ -58,6 +65,7 @@ void print_info(const char *msg, ...) { vsprintf(buf, msg, va); va_end(va); fprintf(stdout, "%s\n", buf); + g_sys.print_log(stdout, buf); } FILE *fopen_nocase(const char *path, const char *filename) { diff --git a/util.h b/util.h index a3a3c7d..72be42b 100644 --- a/util.h +++ b/util.h @@ -22,6 +22,10 @@ extern void print_warning(const char *msg, ...); extern void print_error(const char *msg, ...); extern void print_info(const char *msg, ...); +#ifdef NDEBUG +#define print_debug(x, ...) +#endif + extern FILE * fopen_nocase(const char *path, const char *filename); extern uint16_t fread_le16(FILE *fp);