Import blues from 627051f5

This commit is contained in:
Gregory Montoir 2018-07-13 20:34:11 +08:00
parent 627fa13e25
commit a9b55449cd
13 changed files with 108 additions and 53 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -49,3 +49,23 @@ void decode_amiga_planar8(const uint8_t *src, int w, int h, int depth, uint8_t *
dst += dst_pitch;
}
}
void decode_amiga_blk(const uint8_t *src, uint8_t *dst, int dst_pitch) {
uint16_t data[4];
for (int y = 0; y < 16; ++y) {
for (int p = 0; p < 4; ++p) {
data[p] = READ_BE_UINT16(src); src += 2;
}
for (int b = 0; b < 16; ++b) {
const int mask = 1 << (15 - b);
uint8_t color = 0;
for (int p = 0; p < 4; ++p) {
if (data[p] & mask) {
color |= 1 << p;
}
}
dst[b] = color;
}
dst += dst_pitch;
}
}

View File

@ -6,5 +6,6 @@
extern void decode_ega_spr(const uint8_t *src, int src_pitch, int w, int h, uint8_t *dst, int dst_pitch, int dst_x, int dst_y);
extern void decode_amiga_planar8(const uint8_t *src, int w, int h, int depth, uint8_t *dst, int dst_pitch, int dst_x, int dst_y);
extern void decode_amiga_blk(const uint8_t *src, uint8_t *dst, int dst_pitch);
#endif /* DECODE_H__ */

24
game.c
View File

@ -3,6 +3,12 @@
#include "resource.h"
#include "sys.h"
// palette colors 16..31
static const uint16_t _colors2_data[] = {
0x1a0,0x000,0x1a2,0xfdd,0x1a4,0x678,0x1a6,0x046,0x1a8,0x000,0x1aa,0xa20,0x1ac,0xf87,0x1ae,0x955,
0x1b0,0xbcf,0x1b2,0xfca,0x1b4,0x30a,0x1b6,0xa9a,0x1b8,0x900,0x1ba,0x666,0x1bc,0x747,0x1be,0x020
};
struct vars_t g_vars;
void update_input() {
@ -17,7 +23,7 @@ void update_input() {
void do_title_screen() {
const uint32_t timestamp = g_sys.get_timestamp() + 20 * 1000;
load_img(g_options.amiga_lbms ? "blues.lbm" : "pres.sqz");
load_img(g_options.amiga_data ? "blues.lbm" : "pres.sqz");
fade_in_palette();
do {
update_input();
@ -52,7 +58,7 @@ void do_select_player() {
int frame2 = 1;
const int color_rgb = 2;
const int colors_count = 25;
load_img(g_options.amiga_lbms ? "choix.lbm" : "choix.sqz");
load_img(g_options.amiga_data ? "choix.lbm" : "choix.sqz");
screen_load_graphics();
screen_clear_sprites();
do {
@ -238,7 +244,7 @@ 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_lbms ? "inter.lbm" : "inter.sqz");
load_img(g_options.amiga_data ? "inter.lbm" : "inter.sqz");
g_vars.screen_h = 199;
screen_clear_sprites();
if (g_vars.level > 1) {
@ -284,6 +290,18 @@ void game_main() {
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, "Blues Brothers");
g_vars.start_level = 0;
load_sqv("sprite.sqv", g_res.spr_sqv, 0);
if (g_options.amiga_sprites) {
load_spr("sprite", g_res.spr_sqv, 0);
// load_spr("objet", g_res.spr_sqv, 101);
}
if (g_options.amiga_colors) {
uint16_t palette[16];
for (int i = 0; i < 16; ++i) {
assert(_colors2_data[i * 2] == 0x1a0 + i * 2);
palette[i] = _colors2_data[i * 2 + 1];
}
g_sys.set_palette_amiga(palette, 16);
}
do_title_screen();
while (g_sys.input.quit == 0) {
if (!g_vars.level_completed_flag) {

1
game.h
View File

@ -43,7 +43,6 @@ struct options_t {
bool amiga_copper_bars;
bool amiga_colors;
bool amiga_sprites;
bool amiga_lbms;
bool amiga_data;
};

35
level.c
View File

@ -15,11 +15,6 @@ static const uint16_t _copper_data[18 * MAX_LEVELS] = {
0x198,0x400,0x500,0x600,0x700,0x800,0x900,0xa00,0xb00,0xc00,0xd00,0xe00,0xf00,0xf11,0xf22,0xf33,0xf44,0xf55
};
static const uint16_t _colors2_data[] = {
0x1a0,0x000,0x1a2,0xfdd,0x1a4,0x678,0x1a6,0x046,0x1a8,0x000,0x1aa,0xa20,0x1ac,0xf87,0x1ae,0x955,
0x1b0,0xbcf,0x1b2,0xfca,0x1b4,0x30a,0x1b6,0xa9a,0x1b8,0x900,0x1ba,0x666,0x1bc,0x747,0x1be,0x020
};
static const uint16_t _colors_data[16 * MAX_LEVELS] = {
0x000,0xc77,0x989,0x669,0x147,0xfda,0xdb9,0xf87,0x4af,0x050,0x091,0x111,0xbcf,0xa20,0x630,0xfff,
0x000,0xa67,0xb89,0x067,0x046,0xeb8,0xca5,0xf87,0x4af,0x660,0x980,0x111,0x59c,0xa25,0x635,0xfff,
@ -49,15 +44,18 @@ static const struct {
};
static const struct {
const char *blk;
const char *tbl;
const char *m;
const char *bin;
const char *ennemi;
} _levels_amiga[MAX_LEVELS] = {
{ "mag.m", "magasin.bin" },
{ "ent.m", "entrepo.bin" },
{ "pris.m", "prison.bin" },
{ "egou.m", "egout.bin" },
{ "ville.m", "ville.bin" },
{ 0, "concert.bin" },
{ "mag.blk", "mag.tbl", "mag.m", "magasin.bin", "ennemi1" },
{ "ent.blk", "ent.tbl", "ent.m", "entrepo.bin", "ennemi2" },
{ "prison.blk", "prison.tbl", "pris.m", "prison.bin", "ennemi3" },
{ "egout.blk", "egout.tbl", "egou.m", "egout.bin", "ennemi4" },
{ "ville.blk", "ville.tbl", "ville.m", "ville.bin", "ennemi5" },
{ "concert.blk", "concert.tbl", 0, "concert.bin", "ennemi6" },
};
static const char *_demo_filenames[] = {
@ -76,15 +74,15 @@ void load_level_data(int num) {
load_sql(_levels[num].sql);
}
if (g_options.amiga_data) {
load_blk(_levels_amiga[num].blk);
read_file(_levels_amiga[num].tbl, g_res.sql, 0);
load_bin(_levels_amiga[num].bin);
} else {
load_bin(_levels[num].bin);
}
load_avt(_levels[num].avt, g_res.avt_sqv, 0);
if (g_options.amiga_sprites) {
char name[16];
snprintf(name, sizeof(name), "ennemi%d", 1 + num);
load_spr(name, g_res.tmp, SPRITES_COUNT);
load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT);
} else {
load_sqv(_levels[num].sqv, g_res.tmp, SPRITES_COUNT);
}
@ -304,6 +302,7 @@ static void do_level_update_tiles_anim() {
} else {
const int current = data[0];
num = data[current + 1];
*ptr = num;
t->unk16 = num;
}
if (num >= 128) {
@ -2173,13 +2172,7 @@ void do_level() {
g_sys.set_copper_bars(_copper_data + g_vars.level * 18);
}
if (g_options.amiga_colors) {
uint16_t palette[32];
memcpy(palette, _colors_data + g_vars.level * 16, 16 * sizeof(uint16_t));
for (int i = 0; i < 16; ++i) {
assert(_colors2_data[i * 2] == 0x1a0 + i * 2);
palette[16 + i] = _colors2_data[i * 2 + 1];
}
g_sys.set_palette_amiga(palette);
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
}
// _time_sync_ptr[1] = 1:
g_vars.inp_keyboard[0xB9] = 0; // SPACE

1
main.c
View File

@ -24,7 +24,6 @@ int main(int argc, char *argv[]) {
g_options.amiga_copper_bars = true;
g_options.amiga_colors = true;
// g_options.amiga_sprites = true;
// g_options.amiga_lbms = true;
// g_options.amiga_data = true;
const char *data_path = DEFAULT_DATA_PATH;
if (argc == 2) {

View File

@ -8,7 +8,7 @@
struct resource_data_t g_res;
void res_init() {
static const int SQL_SIZE = 1000 * 16;
static const int SQL_SIZE = 640 * 25;
g_res.sql = (uint8_t *)malloc(SQL_SIZE);
if (!g_res.sql) {
print_error("Failed to allocate sql buffer, %d bytes", SQL_SIZE);
@ -223,6 +223,10 @@ void load_bin(const char *filename) {
}
}
void load_blk(const char *filename) {
read_file(filename, g_res.tiles, 256 * 16 * 8);
}
void load_ck(const char *filename, uint16_t offset) {
const int size = read_compressed_file(filename, g_res.tmp);
switch (offset) {
@ -255,7 +259,7 @@ void load_img(const char *filename) {
memcpy(g_res.vga, g_res.tmp + 32000, 64000);
}
static int load_spr_helper(int offset, const uint8_t *ptr, uint16_t (*read16)(const uint8_t *)) {
static int load_spr_helper(int offset, const uint8_t *ptr, uint16_t (*read16)(const uint8_t *), int depth) {
const int count = read16(ptr); ptr += 6;
print_debug(DBG_RESOURCE, "spr count %d", count);
assert(offset + count <= MAX_SPR_FRAMES);
@ -264,16 +268,18 @@ static int load_spr_helper(int offset, const uint8_t *ptr, uint16_t (*read16)(co
const int h = read16(ptr - 4);
const int w = read16(ptr - 2);
assert((w & 3) == 0);
const int size = (w >> 1) * h + 4;
const int size = h * w * depth / 8;
print_debug(DBG_RESOURCE, "sprite %d, dim %d,%d size %d", i, w, h, size);
ptr += size;
ptr += size + 4;
}
return count;
}
void load_spr(const char *filename, uint8_t *dst, int offset) {
read_file(filename, dst, 0);
const int count = load_spr_helper(offset, dst, READ_BE_UINT16);
// player sprites use 8 colors
const int depth = (offset == 0) ? 3 : 4;
const int count = load_spr_helper(offset, dst, READ_BE_UINT16, depth);
g_res.spr_count = offset + count;
// convert to little endian
uint8_t *ptr = dst;
@ -285,14 +291,14 @@ void load_spr(const char *filename, uint8_t *dst, int offset) {
ptr[4] = w;
ptr[5] = 0;
assert((w & 3) == 0);
const int size = (w >> 1) * h + 4;
ptr += size;
const int size = h * w * depth / 8;
ptr += size + 4;
}
}
void load_sqv(const char *filename, uint8_t *dst, int offset) {
read_compressed_file(filename, dst);
const int count = load_spr_helper(offset, dst, READ_LE_UINT16);
const int count = load_spr_helper(offset, dst, READ_LE_UINT16, 4);
g_res.spr_count = offset + count;
}

View File

@ -54,6 +54,7 @@ extern int read_file(const char *filename, uint8_t *dst, int size);
extern int read_compressed_file(const char *filename, uint8_t *dst);
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_spr(const char *filename, uint8_t *dst, int offset);

View File

@ -160,7 +160,6 @@ void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter) {
}
static void decode_graphics(int spr_type, int start, int end) {
const bool amiga = g_options.amiga_sprites && start != 0;
struct sys_rect_t r[MAX_SPR_FRAMES];
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
if (data) {
@ -170,6 +169,10 @@ static void decode_graphics(int spr_type, int start, int end) {
int max_h = 0;
for (int i = start; i < end; ++i) {
const uint8_t *ptr = g_res.spr_frames[i];
if (!ptr) {
memset(&r[i], 0, sizeof(struct sys_rect_t));
continue;
}
const int h = READ_LE_UINT16(ptr - 4);
const int w = READ_LE_UINT16(ptr - 2);
const int j = i - start;
@ -180,16 +183,16 @@ static void decode_graphics(int spr_type, int start, int end) {
}
current_x = 0;
max_h = h;
if (amiga) {
decode_amiga_planar8(ptr, w / 8, h, 4, data, MAX_SPRITESHEET_W, current_x, current_y);
if (g_options.amiga_sprites) {
decode_amiga_planar8(ptr, w / 8, h, (start == 0) ? 3 : 4, data, MAX_SPRITESHEET_W, current_x, current_y);
} else {
decode_ega_spr(ptr, w, w, h, data, MAX_SPRITESHEET_W, current_x, current_y);
}
r[j].x = current_x;
r[j].y = current_y;
} else {
if (amiga) {
decode_amiga_planar8(ptr, w / 8, h, 4, data, MAX_SPRITESHEET_W, current_x, current_y);
if (g_options.amiga_sprites) {
decode_amiga_planar8(ptr, w / 8, h, (start == 0) ? 3 : 4, data, MAX_SPRITESHEET_W, current_x, current_y);
} else {
decode_ega_spr(ptr, w, w, h, data, MAX_SPRITESHEET_W, current_x, current_y);
}
@ -206,7 +209,8 @@ static void decode_graphics(int spr_type, int start, int end) {
assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H);
render_unload_sprites(spr_type);
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h);
const int palette_offset = (g_options.amiga_sprites && start == 0) ? 16 : 0;
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset);
free(data);
}
}
@ -216,6 +220,7 @@ void screen_load_graphics() {
decode_graphics(RENDER_SPR_GAME, 0, SPRITES_COUNT);
} else {
decode_graphics(RENDER_SPR_LEVEL, SPRITES_COUNT, g_res.spr_count);
// foreground tiles
struct sys_rect_t r[MAX_SPR_FRAMES];
static const int FG_TILE_W = 16;
static const int FG_TILE_H = 16;
@ -230,8 +235,24 @@ void screen_load_graphics() {
r[i].h = FG_TILE_H;
}
render_unload_sprites(RENDER_SPR_FG);
render_load_sprites(RENDER_SPR_FG, g_res.avt_count, r, data, g_res.avt_count * FG_TILE_W, FG_TILE_H);
render_load_sprites(RENDER_SPR_FG, g_res.avt_count, r, data, g_res.avt_count * FG_TILE_W, FG_TILE_H, 0);
free(data);
}
// background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout
if (g_options.amiga_data) {
static const int BG_TILES_COUNT = 256;
static const int W = 320 / 16;
memcpy(g_res.tmp, g_res.tiles, BG_TILES_COUNT * 16 * 8);
for (int i = 0; i < 128; ++i) {
const int y = (i / W);
const int x = (i % W);
decode_amiga_blk(g_res.tmp + i * 16 * 8, g_res.tiles + (y * 640 + x) * 16, 640);
}
for (int i = 128; i < 256; ++i) {
const int y = ((i - 128) / W);
const int x = ((i - 128) % W) + W;
decode_amiga_blk(g_res.tmp + i * 16 * 8, g_res.tiles + (y * 640 + x) * 16, 640);
}
}
}
}

9
sys.h
View File

@ -34,7 +34,7 @@ struct sys_t {
void (*fini)();
void (*set_screen_size)(int w, int h, const char *caption);
void (*set_screen_palette)(const uint8_t *colors, int);
void (*set_palette_amiga)(const uint16_t *colors);
void (*set_palette_amiga)(const uint16_t *colors, int offset);
void (*set_copper_bars)(const uint16_t *data);
void (*fade_in_palette)();
void (*fade_out_palette)();
@ -52,14 +52,11 @@ extern struct sys_t g_sys;
#define RENDER_SPR_GAME 0 /* player sprites */
#define RENDER_SPR_LEVEL 1 /* level sprites */
#define RENDER_SPR_FONT 2 /* font (digits) */
#define RENDER_SPR_FG 3 /* foreground tiles */
#define RENDER_SPR_FG 2 /* foreground tiles */
extern void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h);
extern void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h, int palette_offset);
extern void render_unload_sprites(int spr_type);
extern void render_add_sprite(int spr_type, int frame, int x, int y, int xflip);
extern void render_clear_sprites();
extern void render_draw_tilemap(int x, int y);
extern void render_draw_image();
#endif /* SYS_H__ */

View File

@ -14,7 +14,7 @@ struct spritesheet_t {
SDL_Texture *texture;
};
static struct spritesheet_t _spritesheets[4];
static struct spritesheet_t _spritesheets[3];
struct sprite_t {
int sheet;
@ -102,9 +102,9 @@ static uint32_t convert_amiga_color(uint16_t color) {
return SDL_MapRGB(_fmt, r, g, b);
}
static void sdl2_set_palette_amiga(const uint16_t *colors) {
for (int i = 0; i < 32; ++i) {
_screen_palette[i] = convert_amiga_color(colors[i]);
static void sdl2_set_palette_amiga(const uint16_t *colors, int offset) {
for (int i = 0; i < 16; ++i) {
_screen_palette[offset + i] = convert_amiga_color(colors[i]);
}
}
@ -322,7 +322,7 @@ struct sys_t g_sys = {
.unlock_audio = sdl2_unlock_audio,
};
void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h) {
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) {
assert(spr_type < ARRAYSIZE(_spritesheets));
struct spritesheet_t *spr_sheet = &_spritesheets[spr_type];
spr_sheet->count = count;
@ -341,7 +341,7 @@ void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, co
spr_sheet->texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
SDL_SetTextureBlendMode(spr_sheet->texture, SDL_BLENDMODE_BLEND);
for (int i = 0; i < w * h; ++i) {
argb[i] = (data[i] == 0) ? 0 : (0xFF000000 | _screen_palette[data[i]]);
argb[i] = (data[i] == 0) ? 0 : (0xFF000000 | _screen_palette[palette_offset + data[i]]);
}
SDL_UpdateTexture(spr_sheet->texture, 0, argb, w * sizeof(uint32_t));
free(argb);