Import blues from 6d8f0b2a

This commit is contained in:
Gregory Montoir 2021-12-19 08:09:02 +08:00
parent 140d278724
commit 3f2965eaac
11 changed files with 182 additions and 146 deletions

View File

@ -106,30 +106,32 @@ static void init_level() {
if (g_vars.play_demo_flag) {
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
}
const int xoffs = (TILEMAP_SCREEN_W / 16) / 2;
int xpos = g_options.start_xpos16;
if (xpos < 0) {
xpos = g_vars.level_xpos[OBJECT_NUM_PLAYER1];
if (!g_vars.two_players_flag && (g_vars.objects[OBJECT_NUM_PLAYER1].unk60 || g_vars.objects[OBJECT_NUM_PLAYER2].unk60)) {
xpos = restart_xpos[g_vars.level * 2];
}
xpos = (xpos >> 4) - 10;
xpos = (xpos >> 4) - xoffs;
} else {
g_vars.level_xpos[OBJECT_NUM_PLAYER1] = (xpos << 4) + 10;
g_vars.level_xpos[OBJECT_NUM_PLAYER1] = (xpos << 4) + xoffs;
}
if (xpos < 0) {
xpos = 0;
}
g_vars.screen_tilemap_xorigin = xpos << 4;
const int yoffs = (TILEMAP_SCREEN_H / 16) / 2 + 1;
int ypos = g_options.start_ypos16;
if (ypos < 0) {
ypos = g_vars.level_ypos[OBJECT_NUM_PLAYER1];
if (!g_vars.two_players_flag && (g_vars.objects[OBJECT_NUM_PLAYER1].unk60 || g_vars.objects[OBJECT_NUM_PLAYER2].unk60)) {
ypos = restart_ypos[g_vars.level * 2];
}
ypos = (ypos >> 4) - 6;
ypos = (ypos >> 4) - yoffs;
} else {
g_vars.level_ypos[OBJECT_NUM_PLAYER1] = (ypos << 4) + 6;
g_vars.level_ypos[OBJECT_NUM_PLAYER1] = (ypos << 4) + yoffs;
}
if (ypos < 0) {
ypos = 0;

View File

@ -272,11 +272,17 @@ static void decode_graphics(int spr_type, int start, int end, const uint8_t *dit
max_h = h;
}
}
if (g_res.amiga_data && start == 0) {
for (int i = 0; i < MAX_SPRITESHEET_W * MAX_SPRITESHEET_H; ++i) {
if (data[i] != 0) {
data[i] |= 16;
}
}
}
assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H);
g_sys.render_unload_sprites(spr_type);
const int palette_offset = (g_res.amiga_data && start == 0) ? 16 : 0;
g_sys.render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset, color_key);
g_sys.render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, color_key, false);
free(data);
}
}
@ -305,7 +311,7 @@ void screen_load_graphics(const uint8_t *dither_lut_sqv, const uint8_t *dither_l
dither_graphics(data, FG_TILE_W * g_res.avt_count, FG_TILE_W * g_res.avt_count, FG_TILE_H, dither_lut_avt, color_key);
}
g_sys.render_unload_sprites(RENDER_SPR_FG);
g_sys.render_load_sprites(RENDER_SPR_FG, g_res.avt_count, r, data, g_res.avt_count * FG_TILE_W, FG_TILE_H, 0, color_key);
g_sys.render_load_sprites(RENDER_SPR_FG, g_res.avt_count, r, data, g_res.avt_count * FG_TILE_W, FG_TILE_H, color_key, false);
free(data);
}
// background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout

View File

@ -4,50 +4,43 @@
struct unpack_t {
uint8_t dict_buf[0x200 * 2];
uint8_t rd[0x1000];
};
static struct unpack_t g_unpack;
int unpack(FILE *in, uint8_t *dst) {
fread(g_unpack.rd, 1, 6, in);
const int uncompressed_size = (READ_LE_UINT16(g_unpack.rd) << 16) + READ_LE_UINT16(g_unpack.rd + 2);
const int dict_len = READ_LE_UINT16(g_unpack.rd + 4);
uint8_t buf[6];
fread(buf, 1, 6, in);
const int uncompressed_size = (READ_LE_UINT16(buf) << 16) + READ_LE_UINT16(buf + 2);
const int dict_len = READ_LE_UINT16(buf + 4);
print_debug(DBG_UNPACK, "SQV uncompressed size %d dict_len %d", uncompressed_size, dict_len);
fread(g_unpack.dict_buf, 1, dict_len, in);
const uint8_t *start = dst;
const uint8_t *src = g_unpack.rd;
int len = 1;
int bytes_count = 2;
int bits_count = 1;
uint16_t bits = 0;
uint16_t val = 0;
while ((dst - start) < uncompressed_size) {
--len;
if (len == 0) {
bytes_count -= 2;
if (bytes_count == 0) {
bytes_count = fread(g_unpack.rd, 1, 0x1000, in);
if (bytes_count == 0) {
break;
}
bytes_count += (bytes_count & 1);
src = g_unpack.rd;
--bits_count;
if (bits_count == 0) {
if (fread(buf, 1, 2, in) == 0) {
break;
}
bits = READ_BE_UINT16(src); src += 2;
len = 17;
continue;
bits = READ_BE_UINT16(buf);
bits_count = 16;
}
const int carry = (bits & 0x8000) != 0;
const bool carry = (bits & 0x8000) != 0;
bits <<= 1;
if (carry) {
val += 2;
}
assert(val < 0x400);
assert((val & 1) == 0);
assert(val < dict_len);
val = READ_LE_UINT16(g_unpack.dict_buf + val);
if ((val & 0x8000) == 0) {
continue;
}
assert((val & 0x7F00) == 0);
*dst++ = val & 255;
val = 0;
}

View File

@ -231,7 +231,7 @@ void video_load_sprites() {
assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H);
g_sys.render_unload_sprites(RENDER_SPR_GAME);
g_sys.render_load_sprites(RENDER_SPR_GAME, count, r, data, MAX_SPRITESHEET_W, current_y + max_h, 0, 0x0);
g_sys.render_load_sprites(RENDER_SPR_GAME, count, r, data, MAX_SPRITESHEET_W, current_y + max_h, 0x0, false);
free(data);
}
}

View File

@ -138,23 +138,23 @@ static void level_update_boss_gorilla_init_objects(const uint16_t *p) {
++g_vars.boss.parts[3].y_pos;
}
if (g_vars.boss.hdir) {
g_vars.boss.parts[0].spr_num |= 0x8000;
g_vars.boss.parts[1].spr_num |= 0x8000;
g_vars.boss.parts[2].spr_num |= 0x8000;
g_vars.boss.parts[3].spr_num |= 0x8000;
g_vars.boss.parts[4].spr_num |= 0x8000;
for (int i = 0; i < 5; ++i) {
g_vars.boss.parts[i].spr_num |= 0x8000;
}
}
for (int i = 0; i < 5; ++i) {
struct object_t *obj = &g_vars.objects_tbl[103 + i];
const uint16_t addr = *p++;
if (addr == 0xA609) {
switch (addr) {
case 0xA609:
g_vars.boss.obj1 = obj;
}
if (addr == 0xA60F) {
break;
case 0xA60F:
g_vars.boss.obj2 = obj;
}
if (addr == 0xA603) {
break;
case 0xA603:
g_vars.boss.obj3 = obj;
break;
}
assert(addr == 0xA5F7 || addr == 0xA5FD || addr == 0xA603 || addr == 0xA609 || addr == 0xA60F);
const int num = (addr - 0xA5F7) / 6;
@ -597,7 +597,7 @@ static void level_update_boss_tree() {
g_vars.boss_level5.spr106_pos = 0;
}
uint8_t ah = 1;
if (g_vars.boss_level5.spr106_pos != 0) {
if (g_vars.boss_level5.spr106_pos != 1) {
ah = 3;
g_vars.shake_screen_counter = 4;
obj_player->x_pos += 2;

View File

@ -299,7 +299,7 @@ extern const uint8_t monster_anim_tbl[1100];
extern const uint8_t boss_minotaur_seq_data[86];
extern const uint16_t boss_gorilla_data[19 * 10];
extern const uint16_t boss_gorilla_spr_tbl[46 * 3]; /* uint16_t: spr1_num, uint16_t: spr2_num, int8_t: dx, int8_t: dy */
extern const uint16_t snow_pattern1_data[11];
extern const uint16_t snow_pattern1_data[1];
extern const uint16_t snow_pattern2_data[10];
/* game.c */

View File

@ -944,7 +944,7 @@ static void level_update_tile1(uint16_t offset) {
level_update_tile_type_1(offset);
break;
case 2:
level_update_tile_type_2(offset);
level_update_tile_type_2();
break;
default:
print_warning("Unhandled level_update_tile1 type %d", type);
@ -2097,7 +2097,7 @@ static void level_update_player_anim_0(uint8_t al) {
const uint8_t *anim = level_update_player_anim1_num(18, 36);
level_update_object_anim(anim);
if ((g_vars.level_draw_counter & 3) == 0) {
level_init_object_hit_from_player_pos(&g_vars.objects_tbl[1]);
level_init_object_hit_from_player_pos();
}
g_vars.objects_tbl[1].data.p.current_anim_num = 0;
return;

View File

@ -61,6 +61,9 @@ 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;
while (*s) {
uint8_t code = *s++;
if (code != 0x20) {
@ -68,10 +71,10 @@ void video_draw_string(int offset, int hspace, const char *s) {
if (code > 9) {
code -= 2;
}
decode_planar(g_res.allfonts + code * 48, g_res.vga + offset * 8, 320, 8, 12, 0);
}
++offset;
}
decode_planar(g_res.allfonts + code * 48, dst, GAME_SCREEN_W, 8, 12, 0);
}
dst += 8;
}
}
void video_draw_panel_number(int offset, int num) {
@ -188,7 +191,7 @@ void video_load_front_tiles() {
decode_planar(g_res.frontdat + tile * 16 * 8, g_res.vga + y * w + x, w, 16, 16, 0);
++tile;
if (tile == count) {
g_sys.render_load_sprites(RENDER_SPR_FG, count, r, g_res.vga, w, h, 0, 0x0);
g_sys.render_load_sprites(RENDER_SPR_FG, count, r, g_res.vga, w, h, 0x0, true);
return;
}
}
@ -260,7 +263,7 @@ void video_load_sprites() {
assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H);
g_sys.render_unload_sprites(RENDER_SPR_GAME);
g_sys.render_load_sprites(RENDER_SPR_GAME, count, r, data, MAX_SPRITESHEET_W, current_y + max_h, 0, 0x0);
g_sys.render_load_sprites(RENDER_SPR_GAME, count, r, data, MAX_SPRITESHEET_W, current_y + max_h, 0x0, true);
free(data);
print_debug(DBG_SCREEN, "sprites total_size %d count %d", offset, count);
}

View File

@ -250,7 +250,7 @@ static int unpack_sqv(FILE *in, struct unpack_sqv_t *u) {
int bytes_count = 2;
int state = 0;
int count = 0;
uint8_t code, prev;
uint8_t code, prev = 0;
uint16_t bits = 0;
uint16_t val = 0;
while ((dst - output_buffer) < uncompressed_size) {

2
sys.h
View File

@ -55,7 +55,7 @@ struct sys_t {
void (*stop_audio)();
void (*lock_audio)();
void (*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, int palette_offset, uint8_t color_key);
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);
void (*render_unload_sprites)(int spr_type);
void (*render_add_sprite)(int spr_type, int frame, int x, int y, int xflip);
void (*render_clear_sprites)();

View File

@ -5,16 +5,18 @@
#define COPPER_BARS_H 80
#define MAX_SPRITES 256
#define MAX_SPRITESHEETS 3
static const int FADE_STEPS = 16;
struct spritesheet_t {
int count;
SDL_Rect *r;
SDL_Surface *surface;
SDL_Texture *texture;
};
static struct spritesheet_t _spritesheets[3];
static struct spritesheet_t _spritesheets[MAX_SPRITESHEETS];
struct sprite_t {
int sheet;
@ -33,11 +35,12 @@ static SDL_Window *_window;
static SDL_Renderer *_renderer;
static SDL_Texture *_texture;
static SDL_PixelFormat *_fmt;
static SDL_Palette *_palette;
static uint32_t _screen_palette[256];
static uint32_t *_screen_buffer;
static struct input_t *_input = &g_sys.input;
static int _copper_color;
static int _copper_color_key;
static uint32_t _copper_palette[COPPER_BARS_H];
static SDL_GameController *_controller;
static SDL_Joystick *_joystick;
@ -45,13 +48,10 @@ static int 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;
_window = 0;
_renderer = 0;
_texture = 0;
_fmt = 0;
memset(_screen_palette, 0, sizeof(_screen_palette));
_palette = SDL_AllocPalette(256);
_screen_buffer = 0;
_copper_color = -1;
_copper_color_key = -1;
SDL_GameControllerAddMappingsFromFile("gamecontrollerdb.txt");
_controller = 0;
const int count = SDL_NumJoysticks();
@ -80,6 +80,10 @@ static void sdl2_fini() {
SDL_FreeFormat(_fmt);
_fmt = 0;
}
if (_palette) {
SDL_FreePalette(_palette);
_palette = 0;
}
if (_texture) {
SDL_DestroyTexture(_texture);
_texture = 0;
@ -140,22 +144,33 @@ static uint32_t convert_amiga_color(uint16_t color) {
r |= r << 4;
uint8_t g = (color >> 4) & 15;
g |= g << 4;
uint8_t b = color & 15;
uint8_t b = color & 15;
b |= b << 4;
return SDL_MapRGB(_fmt, r, g, b);
}
static void set_amiga_color(uint16_t color, SDL_Color *p) {
const uint8_t r = (color >> 8) & 15;
p->r = (r << 4) | r;
const uint8_t g = (color >> 4) & 15;
p->g = (g << 4) | g;
const uint8_t b = color & 15;
p->b = (b << 4) | b;
}
static void sdl2_set_palette_amiga(const uint16_t *colors, int offset) {
SDL_Color *palette_colors = &_palette->colors[offset];
for (int i = 0; i < 16; ++i) {
_screen_palette[offset + i] = convert_amiga_color(colors[i]);
set_amiga_color(colors[i], &palette_colors[i]);
}
}
static void sdl2_set_copper_bars(const uint16_t *data) {
if (!data) {
_copper_color = -1;
_copper_color_key = -1;
} else {
_copper_color = (data[0] - 0x180) / 2;
_copper_color_key = (data[0] - 0x180) / 2;
const uint16_t *src = data + 1;
uint32_t *dst = _copper_palette;
for (int i = 0; i < COPPER_BARS_H / 5; ++i) {
@ -170,6 +185,7 @@ static void sdl2_set_copper_bars(const uint16_t *data) {
}
static void sdl2_set_screen_palette(const uint8_t *colors, int offset, int count, int depth) {
SDL_Color *palette_colors = &_palette->colors[offset];
const int shift = 8 - depth;
for (int i = 0; i < count; ++i) {
int r = colors[0];
@ -181,8 +197,18 @@ static void sdl2_set_screen_palette(const uint8_t *colors, int offset, int count
b = (b << shift) | (b >> (depth - shift));
}
_screen_palette[offset + i] = SDL_MapRGB(_fmt, r, g, b);
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];
if (sheet->surface) {
SDL_DestroyTexture(sheet->texture);
sheet->texture = SDL_CreateTextureFromSurface(_renderer, sheet->surface);
}
}
}
static void sdl2_set_palette_color(int i, const uint8_t *colors) {
@ -261,12 +287,12 @@ static void sdl2_transition_screen(enum sys_transition_e type, bool open) {
}
static void sdl2_update_screen(const uint8_t *p, int present) {
if (_copper_color != -1) {
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];
for (int i = 0; i < _screen_w; ++i) {
_screen_buffer[j * _screen_w + i] = (p[i] == _copper_color) ? line_color : _screen_palette[p[i]];
_screen_buffer[j * _screen_w + i] = (p[i] == _copper_color_key) ? line_color : _screen_palette[p[i]];
}
} else {
for (int i = 0; i < _screen_w; ++i) {
@ -310,179 +336,179 @@ static void sdl2_update_screen(const uint8_t *p, int present) {
}
}
static void handle_keyevent(int keysym, bool keydown) {
static void handle_keyevent(int keysym, bool keydown, struct input_t *input) {
switch (keysym) {
case SDLK_LEFT:
if (keydown) {
_input->direction |= INPUT_DIRECTION_LEFT;
input->direction |= INPUT_DIRECTION_LEFT;
} else {
_input->direction &= ~INPUT_DIRECTION_LEFT;
input->direction &= ~INPUT_DIRECTION_LEFT;
}
break;
case SDLK_RIGHT:
if (keydown) {
_input->direction |= INPUT_DIRECTION_RIGHT;
input->direction |= INPUT_DIRECTION_RIGHT;
} else {
_input->direction &= ~INPUT_DIRECTION_RIGHT;
input->direction &= ~INPUT_DIRECTION_RIGHT;
}
break;
case SDLK_UP:
if (keydown) {
_input->direction |= INPUT_DIRECTION_UP;
input->direction |= INPUT_DIRECTION_UP;
} else {
_input->direction &= ~INPUT_DIRECTION_UP;
input->direction &= ~INPUT_DIRECTION_UP;
}
break;
case SDLK_DOWN:
if (keydown) {
_input->direction |= INPUT_DIRECTION_DOWN;
input->direction |= INPUT_DIRECTION_DOWN;
} else {
_input->direction &= ~INPUT_DIRECTION_DOWN;
input->direction &= ~INPUT_DIRECTION_DOWN;
}
break;
case SDLK_RETURN:
case SDLK_SPACE:
_input->space = keydown;
input->space = keydown;
break;
case SDLK_ESCAPE:
_input->escape = keydown;
input->escape = keydown;
break;
case SDLK_1:
_input->digit1 = keydown;
input->digit1 = keydown;
break;
case SDLK_2:
_input->digit2 = keydown;
input->digit2 = keydown;
break;
case SDLK_3:
_input->digit3 = keydown;
input->digit3 = keydown;
break;
}
}
static void handle_controlleraxis(int axis, int value) {
static void handle_controlleraxis(int axis, int value, struct input_t *input) {
static const int THRESHOLD = 3200;
switch (axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
case SDL_CONTROLLER_AXIS_RIGHTX:
if (value < -THRESHOLD) {
_input->direction |= INPUT_DIRECTION_LEFT;
input->direction |= INPUT_DIRECTION_LEFT;
} else {
_input->direction &= ~INPUT_DIRECTION_LEFT;
input->direction &= ~INPUT_DIRECTION_LEFT;
}
if (value > THRESHOLD) {
_input->direction |= INPUT_DIRECTION_RIGHT;
input->direction |= INPUT_DIRECTION_RIGHT;
} else {
_input->direction &= ~INPUT_DIRECTION_RIGHT;
input->direction &= ~INPUT_DIRECTION_RIGHT;
}
break;
case SDL_CONTROLLER_AXIS_LEFTY:
case SDL_CONTROLLER_AXIS_RIGHTY:
if (value < -THRESHOLD) {
_input->direction |= INPUT_DIRECTION_UP;
input->direction |= INPUT_DIRECTION_UP;
} else {
_input->direction &= ~INPUT_DIRECTION_UP;
input->direction &= ~INPUT_DIRECTION_UP;
}
if (value > THRESHOLD) {
_input->direction |= INPUT_DIRECTION_DOWN;
input->direction |= INPUT_DIRECTION_DOWN;
} else {
_input->direction &= ~INPUT_DIRECTION_DOWN;
input->direction &= ~INPUT_DIRECTION_DOWN;
}
break;
}
}
static void handle_controllerbutton(int button, bool pressed) {
static void handle_controllerbutton(int button, bool pressed, struct input_t *input) {
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;
input->space = pressed;
break;
case SDL_CONTROLLER_BUTTON_BACK:
_input->escape = pressed;
input->escape = pressed;
break;
case SDL_CONTROLLER_BUTTON_START:
break;
case SDL_CONTROLLER_BUTTON_DPAD_UP:
if (pressed) {
_input->direction |= INPUT_DIRECTION_UP;
input->direction |= INPUT_DIRECTION_UP;
} else {
_input->direction &= ~INPUT_DIRECTION_UP;
input->direction &= ~INPUT_DIRECTION_UP;
}
break;
case SDL_CONTROLLER_BUTTON_DPAD_DOWN:
if (pressed) {
_input->direction |= INPUT_DIRECTION_DOWN;
input->direction |= INPUT_DIRECTION_DOWN;
} else {
_input->direction &= ~INPUT_DIRECTION_DOWN;
input->direction &= ~INPUT_DIRECTION_DOWN;
}
break;
case SDL_CONTROLLER_BUTTON_DPAD_LEFT:
if (pressed) {
_input->direction |= INPUT_DIRECTION_LEFT;
input->direction |= INPUT_DIRECTION_LEFT;
} else {
_input->direction &= ~INPUT_DIRECTION_LEFT;
input->direction &= ~INPUT_DIRECTION_LEFT;
}
break;
case SDL_CONTROLLER_BUTTON_DPAD_RIGHT:
if (pressed) {
_input->direction |= INPUT_DIRECTION_RIGHT;
input->direction |= INPUT_DIRECTION_RIGHT;
} else {
_input->direction &= ~INPUT_DIRECTION_RIGHT;
input->direction &= ~INPUT_DIRECTION_RIGHT;
}
break;
}
}
static void handle_joystickhatmotion(int value) {
_input->direction = 0;
static void handle_joystickhatmotion(int value, struct input_t *input) {
input->direction = 0;
if (value & SDL_HAT_UP) {
_input->direction |= INPUT_DIRECTION_UP;
input->direction |= INPUT_DIRECTION_UP;
}
if (value & SDL_HAT_DOWN) {
_input->direction |= INPUT_DIRECTION_DOWN;
input->direction |= INPUT_DIRECTION_DOWN;
}
if (value & SDL_HAT_LEFT) {
_input->direction |= INPUT_DIRECTION_LEFT;
input->direction |= INPUT_DIRECTION_LEFT;
}
if (value & SDL_HAT_RIGHT) {
_input->direction |= INPUT_DIRECTION_RIGHT;
input->direction |= INPUT_DIRECTION_RIGHT;
}
}
static void handle_joystickaxismotion(int axis, int value) {
static void handle_joystickaxismotion(int axis, int value, struct input_t *input) {
static const int THRESHOLD = 3200;
switch (axis) {
case 0:
_input->direction &= ~(INPUT_DIRECTION_RIGHT | INPUT_DIRECTION_LEFT);
input->direction &= ~(INPUT_DIRECTION_RIGHT | INPUT_DIRECTION_LEFT);
if (value > THRESHOLD) {
_input->direction |= INPUT_DIRECTION_RIGHT;
input->direction |= INPUT_DIRECTION_RIGHT;
} else if (value < -THRESHOLD) {
_input->direction |= INPUT_DIRECTION_LEFT;
input->direction |= INPUT_DIRECTION_LEFT;
}
break;
case 1:
_input->direction &= ~(INPUT_DIRECTION_UP | INPUT_DIRECTION_DOWN);
input->direction &= ~(INPUT_DIRECTION_UP | INPUT_DIRECTION_DOWN);
if (value > THRESHOLD) {
_input->direction |= INPUT_DIRECTION_DOWN;
input->direction |= INPUT_DIRECTION_DOWN;
} else if (value < -THRESHOLD) {
_input->direction |= INPUT_DIRECTION_UP;
input->direction |= INPUT_DIRECTION_UP;
}
break;
}
}
static void handle_joystickbutton(int button, int pressed) {
static void handle_joystickbutton(int button, int pressed, struct input_t *input) {
if (button == 0) {
_input->space = pressed;
input->space = pressed;
}
}
static int handle_event(const SDL_Event *ev, bool *paused) {
switch (ev->type) {
case SDL_QUIT:
_input->quit = true;
g_sys.input.quit = true;
break;
case SDL_WINDOWEVENT:
switch (ev->window.event) {
@ -494,10 +520,10 @@ static int handle_event(const SDL_Event *ev, bool *paused) {
}
break;
case SDL_KEYUP:
handle_keyevent(ev->key.keysym.sym, 0);
handle_keyevent(ev->key.keysym.sym, 0, &g_sys.input);
break;
case SDL_KEYDOWN:
handle_keyevent(ev->key.keysym.sym, 1);
handle_keyevent(ev->key.keysym.sym, 1, &g_sys.input);
break;
case SDL_CONTROLLERDEVICEADDED:
if (!_controller) {
@ -516,37 +542,37 @@ static int handle_event(const SDL_Event *ev, bool *paused) {
break;
case SDL_CONTROLLERBUTTONUP:
if (_controller) {
handle_controllerbutton(ev->cbutton.button, 0);
handle_controllerbutton(ev->cbutton.button, 0, &g_sys.input);
}
break;
case SDL_CONTROLLERBUTTONDOWN:
if (_controller) {
handle_controllerbutton(ev->cbutton.button, 1);
handle_controllerbutton(ev->cbutton.button, 1, &g_sys.input);
}
break;
case SDL_CONTROLLERAXISMOTION:
if (_controller) {
handle_controlleraxis(ev->caxis.axis, ev->caxis.value);
handle_controlleraxis(ev->caxis.axis, ev->caxis.value, &g_sys.input);
}
break;
case SDL_JOYHATMOTION:
if (_joystick) {
handle_joystickhatmotion(ev->jhat.value);
handle_joystickhatmotion(ev->jhat.value, &g_sys.input);
}
break;
case SDL_JOYAXISMOTION:
if (_joystick) {
handle_joystickaxismotion(ev->jaxis.axis, ev->jaxis.value);
handle_joystickaxismotion(ev->jaxis.axis, ev->jaxis.value, &g_sys.input);
}
break;
case SDL_JOYBUTTONUP:
if (_joystick) {
handle_joystickbutton(ev->jbutton.button, 0);
handle_joystickbutton(ev->jbutton.button, 0, &g_sys.input);
}
break;
case SDL_JOYBUTTONDOWN:
if (_joystick) {
handle_joystickbutton(ev->jbutton.button, 1);
handle_joystickbutton(ev->jbutton.button, 1, &g_sys.input);
}
break;
default:
@ -561,7 +587,7 @@ static void sdl2_process_events() {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
handle_event(&ev, &paused);
if (_input->quit) {
if (g_sys.input.quit) {
break;
}
}
@ -606,39 +632,45 @@ static void sdl2_unlock_audio() {
SDL_UnlockAudio();
}
static void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h, int palette_offset, uint8_t color_key) {
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) {
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));
struct spritesheet_t *sheet = &_spritesheets[spr_type];
sheet->count = count;
sheet->r = (SDL_Rect *)malloc(count * sizeof(SDL_Rect));
for (int i = 0; i < count; ++i) {
SDL_Rect *rect = &spr_sheet->r[i];
SDL_Rect *rect = &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] == color_key) ? 0 : (0xFF000000 | _screen_palette[palette_offset + data[i]]);
}
SDL_UpdateTexture(spr_sheet->texture, 0, argb, w * sizeof(uint32_t));
free(argb);
SDL_Surface *surface = SDL_CreateRGBSurface(0, w, h, 8, 0x0, 0x0, 0x0, 0x0);
SDL_SetSurfacePalette(surface, _palette);
SDL_SetColorKey(surface, 1, color_key);
SDL_LockSurface(surface);
for (int y = 0; y < h; ++y) {
memcpy(((uint8_t *)surface->pixels) + y * surface->pitch, data + y * w, w);
}
SDL_UnlockSurface(surface);
sheet->texture = SDL_CreateTextureFromSurface(_renderer, surface);
if (update_pal) { /* update texture on palette change */
sheet->surface = surface;
} else {
SDL_FreeSurface(sheet->surface);
sheet->surface = 0;
}
}
static 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);
struct spritesheet_t *sheet = &_spritesheets[spr_type];
free(sheet->r);
if (sheet->surface) {
SDL_FreeSurface(sheet->surface);
}
memset(spr_sheet, 0, sizeof(struct spritesheet_t));
if (sheet->texture) {
SDL_DestroyTexture(sheet->texture);
}
memset(sheet, 0, sizeof(struct spritesheet_t));
}
static void render_add_sprite(int spr_type, int frame, int x, int y, int xflip) {