Import blues from ab9ccae9
This commit is contained in:
parent
ce42eaa599
commit
6348a0b0c3
11
README.md
11
README.md
|
@ -30,5 +30,14 @@ By default, the executable loads the data files from the current directory.
|
||||||
This can be changed by using command line switch.
|
This can be changed by using command line switch.
|
||||||
|
|
||||||
```
|
```
|
||||||
./blues --datapath DATA_dos/
|
Usage: blues [OPTIONS]...
|
||||||
|
--datapath=PATH Path to data files (default '.')
|
||||||
|
--level=NUM Start at level NUM
|
||||||
|
--cheats=MASK Cheats bitmask
|
||||||
|
--startpos=XxY Start at position (X,Y)
|
||||||
|
--fullscreen Enable fullscreen
|
||||||
|
--scale Graphics scaling factor (default 2)
|
||||||
|
--filter Graphics scaling filter
|
||||||
|
--screensize=WxH Graphics screen size (default 320x200)
|
||||||
|
--cga Enable CGA colors
|
||||||
```
|
```
|
||||||
|
|
5
game.c
5
game.c
|
@ -55,7 +55,7 @@ void do_select_player() {
|
||||||
const int color_rgb = 2;
|
const int color_rgb = 2;
|
||||||
const int colors_count = 25;
|
const int colors_count = 25;
|
||||||
load_img(g_res.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W, g_options.cga_colors ? 1 : -1);
|
load_img(g_res.amiga_data ? "choix.lbm" : "choix.sqz", GAME_SCREEN_W, g_options.cga_colors ? 1 : -1);
|
||||||
screen_load_graphics();
|
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, 0);
|
||||||
screen_clear_sprites();
|
screen_clear_sprites();
|
||||||
do {
|
do {
|
||||||
screen_copy_img();
|
screen_copy_img();
|
||||||
|
@ -175,7 +175,6 @@ void do_select_player() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// state_default_:
|
|
||||||
if (!fade) {
|
if (!fade) {
|
||||||
fade_in_palette();
|
fade_in_palette();
|
||||||
fade = 1;
|
fade = 1;
|
||||||
|
@ -260,7 +259,7 @@ void game_main() {
|
||||||
load_spr("sprite", g_res.spr_sqv, 0);
|
load_spr("sprite", g_res.spr_sqv, 0);
|
||||||
load_spr("objet", g_res.spr_sqv + SPRITE_SIZE, 101);
|
load_spr("objet", g_res.spr_sqv + SPRITE_SIZE, 101);
|
||||||
} else {
|
} else {
|
||||||
load_sqv("sprite.sqv", g_res.spr_sqv, 0);
|
load_sqv("sprite.sqv", g_res.spr_sqv, 0, g_options.cga_colors ? 2 : -1);
|
||||||
}
|
}
|
||||||
if (g_options.amiga_status_bar || g_res.amiga_data) {
|
if (g_options.amiga_status_bar || g_res.amiga_data) {
|
||||||
uint16_t palette[16];
|
uint16_t palette[16];
|
||||||
|
|
2
game.h
2
game.h
|
@ -258,7 +258,7 @@ extern void screen_add_game_sprite1(int x, int y, int frame);
|
||||||
extern void screen_add_game_sprite2(int x, int y, int frame);
|
extern void screen_add_game_sprite2(int x, int y, int frame);
|
||||||
extern void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter);
|
extern void screen_add_game_sprite3(int x, int y, int frame, int blinking_counter);
|
||||||
extern void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter);
|
extern void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter);
|
||||||
extern void screen_load_graphics();
|
extern void screen_load_graphics(const uint8_t *dither_lut_sqv, const uint8_t *dither_lut_avt);
|
||||||
|
|
||||||
/* sound.c */
|
/* sound.c */
|
||||||
extern void sound_init();
|
extern void sound_init();
|
||||||
|
|
32
level.c
32
level.c
|
@ -34,14 +34,16 @@ static const struct {
|
||||||
const int16_t *xpos;
|
const int16_t *xpos;
|
||||||
const int16_t *ypos;
|
const int16_t *ypos;
|
||||||
uint8_t music;
|
uint8_t music;
|
||||||
uint8_t cga_dither;
|
uint8_t cga_dither_ck;
|
||||||
|
uint8_t cga_dither_sqv;
|
||||||
|
uint8_t cga_dither_avt;
|
||||||
} _levels[MAX_LEVELS] = {
|
} _levels[MAX_LEVELS] = {
|
||||||
{ "mag.ck1", "mag.ck2", "mag.sql", "magasin.bin", "avtmag.sqv", "enemi1.sqv", level_xpos_magasin, level_ypos_magasin, 1, 3 },
|
{ "mag.ck1", "mag.ck2", "mag.sql", "magasin.bin", "avtmag.sqv", "enemi1.sqv", level_xpos_magasin, level_ypos_magasin, 1, 3, 4, 3 },
|
||||||
{ "ent.ck1", "ent.ck2", "ent.sql", "entrepot.bin", "avtent.sqv", "enemi2.sqv", level_xpos_ent, level_ypos_ent, 2, 3 },
|
{ "ent.ck1", "ent.ck2", "ent.sql", "entrepot.bin", "avtent.sqv", "enemi2.sqv", level_xpos_ent, level_ypos_ent, 2, 3, 4, 3 },
|
||||||
{ "prison.ck1", "prison.ck2", "prison.sql", "prison.bin", "avtpris.sqv", "enemi3.sqv", level_xpos_prison, level_ypos_prison, 3, 5 },
|
{ "prison.ck1", "prison.ck2", "prison.sql", "prison.bin", "avtpris.sqv", "enemi3.sqv", level_xpos_prison, level_ypos_prison, 3, 5, 6, 5 },
|
||||||
{ "egou.ck1", "egou.ck2", "egou.sql", "egou.bin", "avtegou.sqv", "enemi4.sqv", level_xpos_egou, level_ypos_egou, 1, 3 },
|
{ "egou.ck1", "egou.ck2", "egou.sql", "egou.bin", "avtegou.sqv", "enemi4.sqv", level_xpos_egou, level_ypos_egou, 1, 3, 4, 3 },
|
||||||
{ "ville.ck1", "ville.ck2", "ville.sql", "ville.bin", "avtville.sqv", "enemi5.sqv", level_xpos_ville, level_ypos_ville, 2, 7 },
|
{ "ville.ck1", "ville.ck2", "ville.sql", "ville.bin", "avtville.sqv", "enemi5.sqv", level_xpos_ville, level_ypos_ville, 2, 7, 4, 7 },
|
||||||
{ "concert.ck1", "concert.ck2", "concert.sql", "concert.bin", "", "enemi6.sqv", level_xpos_concert, level_ypos_concert, 3, 8 },
|
{ "concert.ck1", "concert.ck2", "concert.sql", "concert.bin", "", "enemi6.sqv", level_xpos_concert, level_ypos_concert, 3, 8, 4, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@ -69,7 +71,7 @@ void load_level_data(int num) {
|
||||||
// .avt
|
// .avt
|
||||||
load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT);
|
load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT);
|
||||||
} else {
|
} else {
|
||||||
const int dither_pattern = g_options.cga_colors ? _levels[num].cga_dither : -1;
|
const int dither_pattern = g_options.cga_colors ? _levels[num].cga_dither_ck : -1;
|
||||||
if (num == 0 && g_res.dos_demo) {
|
if (num == 0 && g_res.dos_demo) {
|
||||||
load_ck("demomag.ck1", 0x6000, dither_pattern);
|
load_ck("demomag.ck1", 0x6000, dither_pattern);
|
||||||
load_ck("demomag.ck2", 0x8000, dither_pattern);
|
load_ck("demomag.ck2", 0x8000, dither_pattern);
|
||||||
|
@ -80,8 +82,8 @@ void load_level_data(int num) {
|
||||||
load_sql(_levels[num].sql);
|
load_sql(_levels[num].sql);
|
||||||
}
|
}
|
||||||
load_bin(_levels[num].bin);
|
load_bin(_levels[num].bin);
|
||||||
load_avt(_levels[num].avt, g_res.avt_sqv, 0);
|
load_avt(_levels[num].avt, g_res.avt_sqv, 0, g_options.cga_colors ? _levels[num].cga_dither_avt : -1);
|
||||||
load_sqv(_levels[num].sqv, g_res.tmp, SPRITES_COUNT);
|
load_sqv(_levels[num].sqv, g_res.tmp, SPRITES_COUNT, g_options.cga_colors ? _levels[num].cga_dither_ck : -1);
|
||||||
}
|
}
|
||||||
memcpy(g_vars.level_xpos, _levels[num].xpos, MAX_OBJECTS * sizeof(int16_t));
|
memcpy(g_vars.level_xpos, _levels[num].xpos, MAX_OBJECTS * sizeof(int16_t));
|
||||||
memcpy(g_vars.level_ypos, _levels[num].ypos, MAX_OBJECTS * sizeof(int16_t));
|
memcpy(g_vars.level_ypos, _levels[num].ypos, MAX_OBJECTS * sizeof(int16_t));
|
||||||
|
@ -89,7 +91,11 @@ void load_level_data(int num) {
|
||||||
play_music(_levels[num].music);
|
play_music(_levels[num].music);
|
||||||
g_vars.music_num = _levels[num].music;
|
g_vars.music_num = _levels[num].music;
|
||||||
}
|
}
|
||||||
screen_load_graphics();
|
if (g_options.cga_colors) {
|
||||||
|
} else if (g_options.amiga_colors) {
|
||||||
|
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
|
||||||
|
}
|
||||||
|
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, g_options.cga_colors ? g_res.cga_lut_avt : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_level() {
|
static void init_level() {
|
||||||
|
@ -2096,10 +2102,6 @@ void do_level() {
|
||||||
if (g_options.amiga_copper_bars) {
|
if (g_options.amiga_copper_bars) {
|
||||||
g_sys.set_copper_bars(_copper_data + g_vars.level * 18);
|
g_sys.set_copper_bars(_copper_data + g_vars.level * 18);
|
||||||
}
|
}
|
||||||
if (g_options.cga_colors) {
|
|
||||||
} else if (g_options.amiga_colors) {
|
|
||||||
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
|
|
||||||
}
|
|
||||||
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.screen_draw_offset = TILEMAP_OFFSET_Y * 40;
|
||||||
g_vars.update_objects_counter = 0;
|
g_vars.update_objects_counter = 0;
|
||||||
|
|
25
main.c
25
main.c
|
@ -20,12 +20,13 @@ static const char *USAGE =
|
||||||
"Usage: %s [OPTIONS]...\n"
|
"Usage: %s [OPTIONS]...\n"
|
||||||
" --datapath=PATH Path to data files (default '.')\n"
|
" --datapath=PATH Path to data files (default '.')\n"
|
||||||
" --level=NUM Start at level NUM\n"
|
" --level=NUM Start at level NUM\n"
|
||||||
" --debug=MASK Debug mask\n"
|
" --cheats=MASK Cheats mask\n"
|
||||||
" --startpos=XxY Start at position (X,Y)\n"
|
" --startpos=XxY Start at position (X,Y)\n"
|
||||||
" --fullscreen Enable fullscreen\n"
|
" --fullscreen Enable fullscreen\n"
|
||||||
" --scale Graphics scaling factor (default 2)\n"
|
" --scale Graphics scaling factor (default 2)\n"
|
||||||
" --filter Graphics scaling filter\n"
|
" --filter Graphics scaling filter\n"
|
||||||
" --screensize=WxH Graphics screen size (default 320x200)\n"
|
" --screensize=WxH Graphics screen size (default 320x200)\n"
|
||||||
|
" --cga Enable CGA colors\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
@ -37,7 +38,7 @@ int main(int argc, char *argv[]) {
|
||||||
g_options.amiga_colors = true;
|
g_options.amiga_colors = true;
|
||||||
// g_options.amiga_status_bar = true;
|
// g_options.amiga_status_bar = true;
|
||||||
g_options.dos_scrolling = false;
|
g_options.dos_scrolling = false;
|
||||||
// g_options.cga_colors = true;
|
g_options.cga_colors = false;
|
||||||
const char *data_path = DEFAULT_DATA_PATH;
|
const char *data_path = DEFAULT_DATA_PATH;
|
||||||
int scale_factor = DEFAULT_SCALE_FACTOR;
|
int scale_factor = DEFAULT_SCALE_FACTOR;
|
||||||
const char *scale_filter = DEFAULT_SCALE_FILTER;
|
const char *scale_filter = DEFAULT_SCALE_FILTER;
|
||||||
|
@ -50,15 +51,16 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
static struct option options[] = {
|
static struct option options[] = {
|
||||||
{ "datapath", required_argument, 0, 1 },
|
{ "datapath", required_argument, 0, 1 },
|
||||||
{ "level", required_argument, 0, 2 },
|
{ "level", required_argument, 0, 2 },
|
||||||
{ "debug", required_argument, 0, 3 },
|
{ "debug", required_argument, 0, 3 },
|
||||||
{ "cheats", required_argument, 0, 4 },
|
{ "cheats", required_argument, 0, 4 },
|
||||||
{ "startpos", required_argument, 0, 5 },
|
{ "startpos", required_argument, 0, 5 },
|
||||||
{ "fullscreen", no_argument, 0, 6 },
|
{ "fullscreen", no_argument, 0, 6 },
|
||||||
{ "scale", required_argument, 0, 7 },
|
{ "scale", required_argument, 0, 7 },
|
||||||
{ "filter", required_argument, 0, 8 },
|
{ "filter", required_argument, 0, 8 },
|
||||||
{ "screensize", required_argument, 0, 9 },
|
{ "screensize", required_argument, 0, 9 },
|
||||||
|
{ "cga", no_argument, 0, 10 },
|
||||||
{ 0, 0, 0, 0 },
|
{ 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
int index;
|
int index;
|
||||||
|
@ -98,6 +100,9 @@ int main(int argc, char *argv[]) {
|
||||||
g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40;
|
g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 10:
|
||||||
|
g_options.cga_colors = true;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stdout, USAGE, argv[0]);
|
fprintf(stdout, USAGE, argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
79
resource.c
79
resource.c
|
@ -23,11 +23,6 @@ void res_init(int vga_size) {
|
||||||
if (!g_res.avt_sqv) {
|
if (!g_res.avt_sqv) {
|
||||||
print_error("Failed to allocate avt buffer, %d bytes", AVT_SQV_SIZE);
|
print_error("Failed to allocate avt buffer, %d bytes", AVT_SQV_SIZE);
|
||||||
}
|
}
|
||||||
static const int CGA_SIZE = 160 * 200;
|
|
||||||
g_res.cga = (uint8_t *)malloc(CGA_SIZE);
|
|
||||||
if (!g_res.cga) {
|
|
||||||
print_error("Failed to allocate cga buffer, %d bytes", CGA_SIZE);
|
|
||||||
}
|
|
||||||
const int tmp_size = 32000 + vga_size;
|
const int tmp_size = 32000 + vga_size;
|
||||||
g_res.tmp = (uint8_t *)malloc(tmp_size);
|
g_res.tmp = (uint8_t *)malloc(tmp_size);
|
||||||
if (!g_res.tmp) {
|
if (!g_res.tmp) {
|
||||||
|
@ -69,8 +64,6 @@ void res_fini() {
|
||||||
g_res.avt_sqv = 0;
|
g_res.avt_sqv = 0;
|
||||||
free(g_res.tmp);
|
free(g_res.tmp);
|
||||||
g_res.tmp = 0;
|
g_res.tmp = 0;
|
||||||
free(g_res.cga);
|
|
||||||
g_res.cga = 0;
|
|
||||||
free(g_res.vga);
|
free(g_res.vga);
|
||||||
g_res.vga = 0;
|
g_res.vga = 0;
|
||||||
free(g_res.tiles);
|
free(g_res.tiles);
|
||||||
|
@ -98,54 +91,20 @@ int read_compressed_file(const char *filename, uint8_t *dst) {
|
||||||
extern const uint8_t dither_cga_table[];
|
extern const uint8_t dither_cga_table[];
|
||||||
|
|
||||||
static void dither_cga(int num, uint8_t *dst) {
|
static void dither_cga(int num, uint8_t *dst) {
|
||||||
const uint8_t *_bx = dither_cga_table + num * 32;
|
const uint8_t *p = dither_cga_table + num * 32;
|
||||||
for (int i = 0; i < 256; ++i) { // even lines
|
for (int i = 0; i < 16; ++i, p += 2) {
|
||||||
const uint8_t a = _bx[(i & 15) * 2]; // 0x20 | 0x10
|
dst[i] = p[0] & 3; // even scanline
|
||||||
const uint8_t b = _bx[(i >> 4) * 2 + 1]; // 0x80 | 0x40
|
dst[0x10 + i] = p[1] & 3; // odd scanline
|
||||||
const uint8_t tmp = ((b & 3) << 2) | (a & 3);
|
|
||||||
dst[0x100 + i] = tmp << 4;
|
|
||||||
dst[ i] = tmp;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 256; ++i) { // odd lines
|
|
||||||
const uint8_t a = _bx[(i & 15) * 2 + 1]; // 0x20 | 0x10
|
|
||||||
const uint8_t b = _bx[(i >> 4) * 2]; // 0x80 | 0x40
|
|
||||||
const uint8_t tmp = ((b & 3) << 2) | (a & 3);
|
|
||||||
dst[0x300 + i] = tmp << 4;
|
|
||||||
dst[0x200 + i] = tmp;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 256; ++i) {
|
|
||||||
uint8_t mask = i;
|
|
||||||
static const uint8_t lut[] = { 1, 0, 3, 2 };
|
|
||||||
for (int j = 0; j < 4; ++j) {
|
|
||||||
dst[0x400 + lut[j]] = ((mask & 1) << 7) | ((mask & 2) << 2); // 0x80 | 0x08
|
|
||||||
mask >>= 2;
|
|
||||||
}
|
|
||||||
dst += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copy_cga(const uint8_t *src, uint8_t *di, uint8_t *dither_temp) {
|
static void copy_cga(uint8_t *dst, int dst_pitch, uint8_t *dither_lut) {
|
||||||
for (int y = 0; y < 200; ++y) {
|
for (int y = 0; y < 200; ++y) {
|
||||||
for (int x = 0; x < 40; ++x) {
|
const uint8_t *p = dither_lut + (y & 1) * 0x10;
|
||||||
int a = 0;
|
for (int x = 0; x < 320; ++x) {
|
||||||
int d = 0;
|
dst[x] = p[dst[x]] & 3;
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
const int b = src[i * 40] * 4;
|
|
||||||
a |= READ_LE_UINT16(dither_temp + 0x400 + b) >> (3 - i);
|
|
||||||
d |= READ_LE_UINT16(dither_temp + 0x402 + b) >> (3 - i);
|
|
||||||
}
|
|
||||||
const uint8_t *p = dither_temp + (y & 1) * 0x200;
|
|
||||||
uint8_t _cl = p[a & 255] | p[0x100 + (a >> 8)];
|
|
||||||
uint8_t _ch = p[d & 255] | p[0x100 + (d >> 8)];
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
*di++ = _ch & 3; _ch >>= 2;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
*di++ = _cl & 3; _cl >>= 2;
|
|
||||||
}
|
|
||||||
++src;
|
|
||||||
}
|
}
|
||||||
src += 120;
|
dst += dst_pitch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,9 +177,6 @@ static void load_iff(const uint8_t *data, uint32_t size, uint8_t *dst, int dst_p
|
||||||
memcpy(scanline + scanline_offset, buf + i, code);
|
memcpy(scanline + scanline_offset, buf + i, code);
|
||||||
i += code;
|
i += code;
|
||||||
}
|
}
|
||||||
if (!(cga_dither_pattern < 0)) {
|
|
||||||
memcpy(g_res.cga + offset, scanline + scanline_offset, code);
|
|
||||||
}
|
|
||||||
offset += code;
|
offset += code;
|
||||||
if ((offset % 160) == 0) {
|
if ((offset % 160) == 0) {
|
||||||
decode_bitplane_scanline(scanline, 4, 160, dst + y * dst_pitch);
|
decode_bitplane_scanline(scanline, 4, 160, dst + y * dst_pitch);
|
||||||
|
@ -235,14 +191,13 @@ static void load_iff(const uint8_t *data, uint32_t size, uint8_t *dst, int dst_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(cga_dither_pattern < 0)) {
|
if (!(cga_dither_pattern < 0)) {
|
||||||
uint8_t dither_temp[2048];
|
uint8_t cga_lut[16 * 2];
|
||||||
memset(dither_temp, 0, sizeof(dither_temp));
|
dither_cga(cga_dither_pattern, cga_lut);
|
||||||
dither_cga(cga_dither_pattern, dither_temp);
|
copy_cga(dst, dst_pitch, cga_lut);
|
||||||
copy_cga(g_res.cga, dst, dither_temp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_avt(const char *filename, uint8_t *dst, int offset) {
|
void load_avt(const char *filename, uint8_t *dst, int offset, int dither_pattern) {
|
||||||
read_compressed_file(filename, dst);
|
read_compressed_file(filename, dst);
|
||||||
const uint8_t *ptr = dst;
|
const uint8_t *ptr = dst;
|
||||||
const int count = READ_LE_UINT16(ptr); ptr += 6;
|
const int count = READ_LE_UINT16(ptr); ptr += 6;
|
||||||
|
@ -252,6 +207,9 @@ void load_avt(const char *filename, uint8_t *dst, int offset) {
|
||||||
ptr += 132;
|
ptr += 132;
|
||||||
}
|
}
|
||||||
g_res.avt_count = count;
|
g_res.avt_count = count;
|
||||||
|
if (!(dither_pattern < 0)) {
|
||||||
|
dither_cga(dither_pattern, g_res.cga_lut_avt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint8_t *trigger_lookup_table1(uint8_t num) {
|
static const uint8_t *trigger_lookup_table1(uint8_t num) {
|
||||||
|
@ -388,10 +346,13 @@ void load_spr(const char *filename, uint8_t *dst, int offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_sqv(const char *filename, uint8_t *dst, int offset) {
|
void load_sqv(const char *filename, uint8_t *dst, int offset, int dither_pattern) {
|
||||||
read_compressed_file(filename, dst);
|
read_compressed_file(filename, dst);
|
||||||
const int count = load_spr_helper(offset, dst, READ_LE_UINT16, 4);
|
const int count = load_spr_helper(offset, dst, READ_LE_UINT16, 4);
|
||||||
g_res.spr_count = offset + count;
|
g_res.spr_count = offset + count;
|
||||||
|
if (!(dither_pattern < 0)) {
|
||||||
|
dither_cga(dither_pattern, g_res.cga_lut_sqv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_sql(const char *filename) {
|
void load_sql(const char *filename) {
|
||||||
|
|
|
@ -39,13 +39,14 @@ struct resource_data_t {
|
||||||
const uint8_t *spr_frames[MAX_SPR_FRAMES];
|
const uint8_t *spr_frames[MAX_SPR_FRAMES];
|
||||||
uint8_t palette[16 * 3];
|
uint8_t palette[16 * 3];
|
||||||
struct trigger_t triggers[MAX_TRIGGERS];
|
struct trigger_t triggers[MAX_TRIGGERS];
|
||||||
uint8_t *cga;
|
|
||||||
uint8_t *vga;
|
uint8_t *vga;
|
||||||
int vga_size;
|
int vga_size;
|
||||||
uint8_t *tiles;
|
uint8_t *tiles;
|
||||||
uint8_t *snd;
|
uint8_t *snd;
|
||||||
bool dos_demo;
|
bool dos_demo;
|
||||||
bool amiga_data;
|
bool amiga_data;
|
||||||
|
uint8_t cga_lut_avt[16 * 2];
|
||||||
|
uint8_t cga_lut_sqv[16 * 2];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct resource_data_t g_res;
|
extern struct resource_data_t g_res;
|
||||||
|
@ -54,14 +55,14 @@ extern void res_init(int vga_size);
|
||||||
extern void res_fini();
|
extern void res_fini();
|
||||||
extern int read_file(const char *filename, uint8_t *dst, int size);
|
extern int read_file(const char *filename, uint8_t *dst, int size);
|
||||||
extern int read_compressed_file(const char *filename, uint8_t *dst);
|
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_avt(const char *filename, uint8_t *dst, int offset, int dither_pattern);
|
||||||
extern void load_bin(const char *filename);
|
extern void load_bin(const char *filename);
|
||||||
extern void load_blk(const char *filename);
|
extern void load_blk(const char *filename);
|
||||||
extern void load_ck(const char *filename, uint16_t offset, int dither_pattern);
|
extern void load_ck(const char *filename, uint16_t offset, int dither_pattern);
|
||||||
extern void load_img(const char *filename, int screen_w, int dither_pattern);
|
extern void load_img(const char *filename, int screen_w, int dither_pattern);
|
||||||
extern void load_m(const char *filename);
|
extern void load_m(const char *filename);
|
||||||
extern void load_spr(const char *filename, uint8_t *dst, int offset);
|
extern void load_spr(const char *filename, uint8_t *dst, int offset);
|
||||||
extern void load_sqv(const char *filename, uint8_t *dst, int offset);
|
extern void load_sqv(const char *filename, uint8_t *dst, int offset, int dither_pattern);
|
||||||
extern void load_sql(const char *filename);
|
extern void load_sql(const char *filename);
|
||||||
extern uint8_t * lookup_sql(int x, int y);
|
extern uint8_t * lookup_sql(int x, int y);
|
||||||
|
|
||||||
|
|
41
screen.c
41
screen.c
|
@ -199,10 +199,26 @@ void screen_add_game_sprite4(int x, int y, int frame, int blinking_counter) {
|
||||||
// print_warning("screen_add_game_sprite4");
|
// print_warning("screen_add_game_sprite4");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_graphics(int spr_type, int start, int end) {
|
static void dither_graphics(uint8_t *dst, int dst_pitch, int w, int h, const uint8_t *dither_lut, uint8_t color_key) {
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
const uint8_t *p = dither_lut + (y & 1) * 0x10;
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
const uint8_t color = dst[x];
|
||||||
|
if (color == 0) {
|
||||||
|
dst[x] = color_key;
|
||||||
|
} else {
|
||||||
|
dst[x] = p[color] & 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst += dst_pitch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void decode_graphics(int spr_type, int start, int end, const uint8_t *dither_lut) {
|
||||||
struct sys_rect_t r[MAX_SPR_FRAMES];
|
struct sys_rect_t r[MAX_SPR_FRAMES];
|
||||||
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
|
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
const uint8_t color_key = dither_lut ? 0x20 : 0;
|
||||||
const int depth = g_res.amiga_data && (start == 0) ? 3 : 4;
|
const int depth = g_res.amiga_data && (start == 0) ? 3 : 4;
|
||||||
int current_x = 0;
|
int current_x = 0;
|
||||||
int max_w = 0;
|
int max_w = 0;
|
||||||
|
@ -230,6 +246,9 @@ static void decode_graphics(int spr_type, int start, int end) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
decode_spr(ptr, w, w, h, depth, data, MAX_SPRITESHEET_W, current_x, current_y, g_res.amiga_data);
|
decode_spr(ptr, w, w, h, depth, data, MAX_SPRITESHEET_W, current_x, current_y, g_res.amiga_data);
|
||||||
|
if (dither_lut) {
|
||||||
|
dither_graphics(data + current_y * MAX_SPRITESHEET_W + current_x, MAX_SPRITESHEET_W, w, h, dither_lut, color_key);
|
||||||
|
}
|
||||||
r[j].x = current_x;
|
r[j].x = current_x;
|
||||||
r[j].y = current_y;
|
r[j].y = current_y;
|
||||||
r[j].w = w;
|
r[j].w = w;
|
||||||
|
@ -243,17 +262,18 @@ static void decode_graphics(int spr_type, int start, int end) {
|
||||||
assert(current_y + max_h <= MAX_SPRITESHEET_H);
|
assert(current_y + max_h <= MAX_SPRITESHEET_H);
|
||||||
render_unload_sprites(spr_type);
|
render_unload_sprites(spr_type);
|
||||||
const int palette_offset = (g_res.amiga_data && start == 0) ? 16 : 0;
|
const int palette_offset = (g_res.amiga_data && start == 0) ? 16 : 0;
|
||||||
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset);
|
render_load_sprites(spr_type, end - start, r, data, MAX_SPRITESHEET_W, current_y + max_h, palette_offset, color_key);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void screen_load_graphics() {
|
void screen_load_graphics(const uint8_t *dither_lut_sqv, const uint8_t *dither_lut_avt) {
|
||||||
if (g_res.spr_count <= SPRITES_COUNT) {
|
if (g_res.spr_count <= SPRITES_COUNT) {
|
||||||
decode_graphics(RENDER_SPR_GAME, 0, g_res.spr_count);
|
decode_graphics(RENDER_SPR_GAME, 0, g_res.spr_count, dither_lut_sqv);
|
||||||
} else {
|
} else {
|
||||||
decode_graphics(RENDER_SPR_LEVEL, SPRITES_COUNT, g_res.spr_count);
|
decode_graphics(RENDER_SPR_LEVEL, SPRITES_COUNT, g_res.spr_count, dither_lut_sqv);
|
||||||
// foreground tiles
|
// foreground tiles
|
||||||
|
const uint8_t color_key = dither_lut_avt ? 0x20 : 0;
|
||||||
struct sys_rect_t r[MAX_SPR_FRAMES];
|
struct sys_rect_t r[MAX_SPR_FRAMES];
|
||||||
static const int FG_TILE_W = 16;
|
static const int FG_TILE_W = 16;
|
||||||
static const int FG_TILE_H = 16;
|
static const int FG_TILE_H = 16;
|
||||||
|
@ -267,24 +287,27 @@ void screen_load_graphics() {
|
||||||
r[i].w = FG_TILE_W;
|
r[i].w = FG_TILE_W;
|
||||||
r[i].h = FG_TILE_H;
|
r[i].h = FG_TILE_H;
|
||||||
}
|
}
|
||||||
|
if (dither_lut_avt) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
render_unload_sprites(RENDER_SPR_FG);
|
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, 0);
|
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);
|
||||||
free(data);
|
free(data);
|
||||||
}
|
}
|
||||||
// background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout
|
// background tiles (Amiga) - re-arrange to match DOS .ck1/.ck2 layout
|
||||||
if (g_res.amiga_data) {
|
if (g_res.amiga_data) {
|
||||||
static const int BG_TILES_COUNT = 256;
|
static const int BG_TILES_COUNT = 256;
|
||||||
static const int W = 320 / 16;
|
static const int W = 320 / 16;
|
||||||
memcpy(g_res.tmp, g_res.tiles, BG_TILES_COUNT * 16 * 8);
|
memcpy(g_res.vga, g_res.tiles, BG_TILES_COUNT * 16 * 8);
|
||||||
for (int i = 0; i < 128; ++i) {
|
for (int i = 0; i < 128; ++i) {
|
||||||
const int y = (i / W);
|
const int y = (i / W);
|
||||||
const int x = (i % W);
|
const int x = (i % W);
|
||||||
decode_amiga_blk(g_res.tmp + i * 16 * 8, g_res.tiles + (y * 640 + x) * 16, 640);
|
decode_amiga_blk(g_res.vga + i * 16 * 8, g_res.tiles + (y * 640 + x) * 16, 640);
|
||||||
}
|
}
|
||||||
for (int i = 128; i < 256; ++i) {
|
for (int i = 128; i < 256; ++i) {
|
||||||
const int y = ((i - 128) / W);
|
const int y = ((i - 128) / W);
|
||||||
const int x = ((i - 128) % W) + 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);
|
decode_amiga_blk(g_res.vga + i * 16 * 8, g_res.tiles + (y * 640 + x) * 16, 640);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
sys.h
2
sys.h
|
@ -57,7 +57,7 @@ extern struct sys_t g_sys;
|
||||||
#define RENDER_SPR_LEVEL 1 /* level sprites */
|
#define RENDER_SPR_LEVEL 1 /* level sprites */
|
||||||
#define RENDER_SPR_FG 2 /* 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, int palette_offset);
|
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, uint8_t color_key);
|
||||||
extern void render_unload_sprites(int spr_type);
|
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_add_sprite(int spr_type, int frame, int x, int y, int xflip);
|
||||||
extern void render_clear_sprites();
|
extern void render_clear_sprites();
|
||||||
|
|
|
@ -503,7 +503,7 @@ struct sys_t g_sys = {
|
||||||
.unlock_audio = sdl2_unlock_audio,
|
.unlock_audio = sdl2_unlock_audio,
|
||||||
};
|
};
|
||||||
|
|
||||||
void render_load_sprites(int spr_type, int count, const struct sys_rect_t *r, const uint8_t *data, int w, int h, int palette_offset) {
|
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) {
|
||||||
assert(spr_type < ARRAYSIZE(_spritesheets));
|
assert(spr_type < ARRAYSIZE(_spritesheets));
|
||||||
struct spritesheet_t *spr_sheet = &_spritesheets[spr_type];
|
struct spritesheet_t *spr_sheet = &_spritesheets[spr_type];
|
||||||
spr_sheet->count = count;
|
spr_sheet->count = count;
|
||||||
|
@ -522,7 +522,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);
|
spr_sheet->texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, w, h);
|
||||||
SDL_SetTextureBlendMode(spr_sheet->texture, SDL_BLENDMODE_BLEND);
|
SDL_SetTextureBlendMode(spr_sheet->texture, SDL_BLENDMODE_BLEND);
|
||||||
for (int i = 0; i < w * h; ++i) {
|
for (int i = 0; i < w * h; ++i) {
|
||||||
argb[i] = (data[i] == 0) ? 0 : (0xFF000000 | _screen_palette[palette_offset + data[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));
|
SDL_UpdateTexture(spr_sheet->texture, 0, argb, w * sizeof(uint32_t));
|
||||||
free(argb);
|
free(argb);
|
||||||
|
|
|
@ -851,7 +851,6 @@ void triggers_update_tiles1(struct object_t *obj) {
|
||||||
obj35->ypos16 = obj->ypos16;
|
obj35->ypos16 = obj->ypos16;
|
||||||
obj35->anim_num = 1;
|
obj35->anim_num = 1;
|
||||||
obj35->animframes_ptr = animframes_059d + obj35->type * 116 / 4;
|
obj35->animframes_ptr = animframes_059d + obj35->type * 116 / 4;
|
||||||
// seg003:12A3
|
|
||||||
if (_di == 0) {
|
if (_di == 0) {
|
||||||
do_level_update_tile(obj->xpos16, obj->ypos16, p[2]);
|
do_level_update_tile(obj->xpos16, obj->ypos16, p[2]);
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue