Import blues from e49bacb8

This commit is contained in:
Gregory Montoir 2018-12-16 20:34:03 +08:00
parent 6348a0b0c3
commit 75a4b6508c
34 changed files with 5145 additions and 154 deletions

View File

@ -2,16 +2,26 @@
SDL_CFLAGS := `sdl2-config --cflags`
SDL_LIBS := `sdl2-config --libs`
SRCS := decode.c fileio.c game.c level.c main.c opcodes.c resource.c screen.c sound.c staticres.c sys_sdl2.c triggers.c unpack.c util.c
BB := decode.c fileio.c game.c level.c objects.c resource.c screen.c sound.c staticres.c tiles.c unpack.c
JA := game.c level.c resource.c screen.c sound.c staticres.c unpack.c
BB_SRCS := $(foreach f,$(BB),bb/$f)
JA_SRCS := $(foreach f,$(JA),ja/$f)
SRCS := $(BB_SRCS) $(JA_SRCS)
OBJS := $(SRCS:.c=.o)
DEPS := $(SRCS:.c=.d)
CPPFLAGS := -Wall -Wpedantic -MMD $(SDL_CFLAGS) -g
CPPFLAGS := -Wall -Wpedantic -MMD $(SDL_CFLAGS) -I. -g
blues: $(OBJS)
$(CC) $(LDFLAGS) -o $@ $(OBJS) $(SDL_LIBS) -lmodplug
all: blues bbja
blues: main.o sys_sdl2.o util.o $(BB_SRCS:.c=.o)
$(CC) $(LDFLAGS) -o $@ $^ $(SDL_LIBS) -lmodplug
bbja: main.o sys_sdl2.o util.o $(JA_SRCS:.c=.o)
$(CC) $(LDFLAGS) -o $@ $^ $(SDL_LIBS) -lmodplug
clean:
rm -f *.o *.d
rm -f $(OBJS) $(DEPS)
-include $(DEPS)

View File

@ -1,33 +1,36 @@
# Blues Brothers
This is a rewrite of the game [Blues Brothers](https://www.mobygames.com/game/blues-brothers) developed by [Titus](https://www.mobygames.com/company/titus-interactive-sa).
This is a rewrite of the [Blues Brothers](https://www.mobygames.com/game/blues-brothers) and [Blues Brothers: Jukebox Adventure](https://www.mobygames.com/game/blues-brothers-jukebox-adventure) game engines developed by [Titus Interactive](https://www.mobygames.com/company/titus-interactive-sa).
![Screenshot1](blues1.png) ![Screenshot2](blues2.png)
![Screenshot1](blues1.png) ![Screenshot2](bbja2.png)
## Requirements
### Blues Brothers
The game data files of the DOS or Amiga version are required.
```
*.BIN, *.CK1, *.CK2, *.SQL, *.SQV, *.SQZ
```
For sounds and music, the Amiga version files need to be copied.
For sounds and music, the Amiga version files or the [ExoticA](https://www.exotica.org.uk/wiki/The_Blues_Brothers) set need to be copied.
### Jukebox Adventure
The game data files of the DOS version are required.
```
SOUND, ALMOST, GUNN, EVERY, SHOT
*.EAT, *.MOD
```
The [ExoticA](https://www.exotica.org.uk/wiki/The_Blues_Brothers) modules set can also be used.
## Running
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 using command line switches.
```
Usage: blues [OPTIONS]...
@ -36,8 +39,8 @@ Usage: blues [OPTIONS]...
--cheats=MASK Cheats bitmask
--startpos=XxY Start at position (X,Y)
--fullscreen Enable fullscreen
--scale Graphics scaling factor (default 2)
--filter Graphics scaling filter
--scale=N Graphics scaling factor (default 2)
--filter=NAME Graphics scaling filter (default 'nearest')
--screensize=WxH Graphics screen size (default 320x200)
--cga Enable CGA colors
```

View File

@ -31,7 +31,7 @@ void update_input() {
// g_vars.inp_key_tab = g_vars.inp_keyboard[0xF] || g_vars.inp_keyboard[0x78];
}
void do_title_screen() {
static void do_title_screen() {
const uint32_t timestamp = g_sys.get_timestamp() + 20 * 1000;
load_img(g_res.amiga_data ? "blues.lbm" : "pres.sqz", GAME_SCREEN_W, g_options.cga_colors ? 0 : -1);
fade_in_palette();
@ -40,13 +40,33 @@ void do_title_screen() {
if (g_sys.input.space || g_sys.input.quit) {
break;
}
g_sys.sleep(10);
} while (g_sys.get_timestamp() < timestamp);
play_sound(SOUND_0);
fade_out_palette();
g_sys.input.space = 0;
}
void do_select_player() {
static void do_demo_screens() {
static const char *filenames[] = { "text1.sqz", "maq1.sqz", "maq2.sqz", "maq3.sqz", "maq4.sqz", "maq5.sqz", 0 };
for (int i = 0; filenames[i]; ++i) {
load_img(filenames[i], GAME_SCREEN_W, -1);
fade_in_palette();
while (1) {
update_input();
if (g_sys.input.space) {
break;
}
if (g_sys.input.quit) {
return;
}
g_sys.sleep(10);
}
fade_out_palette();
}
}
static void do_select_player() {
int quit = 0;
int fade = 0;
int state = 0;
@ -58,7 +78,6 @@ void do_select_player() {
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, 0);
screen_clear_sprites();
do {
screen_copy_img();
update_input();
const uint32_t timestamp = g_sys.get_timestamp();
switch (state) {
@ -300,7 +319,7 @@ void game_main() {
g_res.spr_frames[144] = icon778e;
}
if (g_options.cga_colors) {
g_sys.set_screen_palette(_colors_cga, 4);
g_sys.set_screen_palette(_colors_cga, 0, 4, 8);
} else if (g_options.amiga_colors) {
uint16_t palette[16];
for (int i = 0; i < 16; ++i) {
@ -328,6 +347,23 @@ void game_main() {
}
load_level_data(g_vars.level);
do_level();
if (g_res.dos_demo && g_vars.level > 0) {
do_demo_screens();
return;
}
}
}
}
static void game_run(const char *data_path) {
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
sound_init();
game_main();
sound_fini();
res_fini();
}
struct game_t game = {
"Blues Brothers",
game_run
};

View File

@ -4,9 +4,6 @@
#include "intern.h"
#define GAME_SCREEN_W g_options.screen_w
#define GAME_SCREEN_H g_options.screen_h
#define TILEMAP_OFFSET_Y 14
#define TILEMAP_SCREEN_W GAME_SCREEN_W
#define TILEMAP_SCREEN_H (GAME_SCREEN_H - 40)
@ -38,20 +35,6 @@
#define CHEATS_UNLIMITED_LIFES (1 << 1)
#define CHEATS_UNLIMITED_ENERGY (1 << 2)
struct options_t {
uint32_t cheats;
int start_level;
int start_xpos16;
int start_ypos16;
int screen_w;
int screen_h;
bool amiga_copper_bars;
bool amiga_colors;
bool amiga_status_bar;
bool dos_scrolling;
bool cga_colors;
};
extern struct options_t g_options;
struct door_t {
@ -134,15 +117,15 @@ struct object_t {
uint8_t unk56;
int16_t vinyls_count;
uint8_t collide_flag;
int16_t unk5A; // always zero
uint8_t unk5C;
// int16_t unk5A; // always zero
// uint8_t unk5C; // never read
uint8_t unk5D;
uint8_t blinking_counter;
uint8_t data5F; // music instrument number for obj39/40, counter for other objects
uint8_t unk60;
uint8_t lifes_count;
uint8_t flag_end_level; // level flag, set if music instrument was found
uint8_t unk63; // restart_level_flag
uint8_t level_complete_flag; // set if music instrument was found
uint8_t restart_level_flag;
};
struct vars_t {
@ -220,8 +203,6 @@ extern uint8_t *level_tilesdata_1e8c[];
/* game.c */
extern void update_input();
extern void game_main();
extern void do_title_screen();
extern void do_select_player();
/* level.c */
extern void load_level_data(int num);
@ -233,7 +214,7 @@ extern void do_level_drop_grabbed_object(struct object_t *);
extern void do_level_update_projectile(struct object_t *obj);
extern void do_level();
/* opcodes.c */
/* objects.c */
extern void level_call_object_func(struct object_t *);
/* screen.c */
@ -247,7 +228,6 @@ 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_copy_img();
extern void screen_unk5();
extern void screen_do_transition1(int a);
extern void screen_do_transition2();
@ -266,14 +246,14 @@ extern void sound_fini();
extern void play_sound(int num);
extern void play_music(int num);
/* triggers.c */
/* tiles.c */
extern uint16_t triggers_get_tile_type(int x, int y);
extern uint16_t triggers_get_next_tile_flags(int x, int y);
extern uint16_t triggers_get_tile_data(struct object_t *obj);
extern uint16_t triggers_get_next_tile_num(int x, int y);
extern void level_call_trigger_func(struct object_t *obj, int y);
extern void triggers_update_tiles1(struct object_t *obj);
extern int16_t triggers_get_dy(struct object_t *obj);
extern int16_t triggers_tile_get_yoffset(struct object_t *obj);
extern void triggers_update_tiles2(struct object_t *obj);
#endif /* GAME_H__ */

View File

@ -94,6 +94,8 @@ void load_level_data(int num) {
if (g_options.cga_colors) {
} else if (g_options.amiga_colors) {
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
} else {
g_sys.set_screen_palette(g_res.palette, 0, 16, 8);
}
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, g_options.cga_colors ? g_res.cga_lut_avt : 0);
}
@ -229,13 +231,13 @@ static void init_level() {
obj->trigger3 = 0;
obj->unk50 = 0;
// obj->unk4E = 0;
if (obj->unk63 == 0 && obj->flag_end_level == 0 && (g_vars.level == 0 || g_vars.play_demo_flag)) {
if (obj->restart_level_flag == 0 && obj->level_complete_flag == 0 && (g_vars.level == 0 || g_vars.play_demo_flag)) {
g_vars.player1_dead_flag = 0;
g_vars.player2_scrolling_flag = 0;
obj->lifes_count = 3;
obj->data51 = 3;
obj->vinyls_count = 0;
} else if (obj->unk63 != 0) {
} else if (obj->restart_level_flag != 0) {
--obj->lifes_count;
obj->data51 = 3;
obj->vinyls_count = 0;
@ -244,15 +246,15 @@ static void init_level() {
obj->lifes_count = 3;
obj->data51 = 3;
}
obj->unk63 = 0;
obj->flag_end_level = 0;
obj->restart_level_flag = 0;
obj->level_complete_flag = 0;
obj->unk53 = 0;
obj->unk54 = 0;
obj->unk55 = 0;
obj->unk56 = 0;
obj->collide_flag = 0;
obj->unk5A = 0;
obj->unk5C = 1;
// obj->unk5A = 0;
// obj->unk5C = 1;
obj->unk5D = 0;
if (obj->ypos > g_vars.screen_tilemap_h) {
obj->unk53 = 1;
@ -789,17 +791,17 @@ static void do_level_add_sprite3(struct object_t *obj) {
obj->anim_num = 1;
obj->special_anim = 0;
obj->sprite3_counter = 0;
} else if (obj->unk5A != 0) {
obj->unk5C = 4;
// } else if (obj->unk5A != 0) {
// obj->unk5C = 4;
}
}
if (obj->special_anim == 18 && obj->anim_num > 8 && (g_vars.inp_key_up != 0 /* || g_inp_key_T != 0*/)) {
obj->anim_num = 1;
obj->special_anim = 0;
obj->sprite3_counter = 0;
if (obj->unk5A != 0) {
obj->unk5C = 4;
}
// if (obj->unk5A != 0) {
// obj->unk5C = 4;
// }
}
}
if (obj->type != 100) {
@ -998,7 +1000,7 @@ void do_level_update_panel_lifes(struct object_t *obj) {
}
if (obj->data51 == 0) { // health
if (!g_vars.two_players_flag) {
obj->unk63 = 1;
obj->restart_level_flag = 1;
g_vars.game_over_flag = 1;
} else {
if (obj->lifes_count != 1) {
@ -1151,12 +1153,6 @@ void do_level_enter_door(struct object_t *obj) {
}
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
draw_level_panel();
do_level_update_panel_vinyls(obj);
if (g_vars.two_players_flag) {
do_level_update_panel_2nd_player();
}
screen_flip();
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
do_level_update_scrolling2();
draw_level_panel();
@ -1164,8 +1160,8 @@ void do_level_enter_door(struct object_t *obj) {
if (g_vars.two_players_flag) {
do_level_update_panel_2nd_player();
}
screen_do_transition1(1);
screen_flip();
screen_do_transition1(1);
obj->unk3D = 0;
obj->sprite_type = 0;
obj->yacc = 2;
@ -1456,7 +1452,7 @@ static void do_level_fixup_object_position(struct object_t *obj) {
switch (num) {
case 2:
case 14:
ret = triggers_get_dy(obj);
ret = triggers_tile_get_yoffset(obj);
obj->ypos = ret + (obj->ypos & ~15);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
@ -1464,7 +1460,7 @@ static void do_level_fixup_object_position(struct object_t *obj) {
case 3:
case 15:
--obj->ypos16;
ret = triggers_get_dy(obj);
ret = triggers_tile_get_yoffset(obj);
obj->ypos = ret + (obj->ypos & ~15) - 16;
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
@ -1909,7 +1905,6 @@ static void do_level_update_objects() {
}
} else if (g_vars.two_players_flag) {
if (!g_vars.player1_dead_flag) {
// sub_176D7(obj);
do_level_update_object_unk2E(obj);
do_level_update_panel_2nd_player();
}
@ -1918,8 +1913,8 @@ static void do_level_update_objects() {
}
}
} else if (obj->type > 2 && obj->collide_flag == 0) {
const int x = g_vars.level_xpos[i]; // _si
const int y = g_vars.level_ypos[i]; // _di
const int x = g_vars.level_xpos[i];
const int y = g_vars.level_ypos[i];
if (obj->type == 32) {
obj->unk5D = i;
}
@ -1992,16 +1987,16 @@ static void do_level_update_objects() {
}
}
}
if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level != 0) {
if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0) {
g_vars.level_completed_flag = 1;
} else {
if (g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level != 0 && g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level != 0) {
if (g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0 && g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag != 0) {
g_vars.level_completed_flag = 1;
}
if (g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level != 0 && g_vars.player1_dead_flag) {
if (g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0 && g_vars.player1_dead_flag) {
g_vars.level_completed_flag = 1;
}
if (g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level != 0 && g_vars.player2_dead_flag) {
if (g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag != 0 && g_vars.player2_dead_flag) {
g_vars.level_completed_flag = 1;
}
}
@ -2019,8 +2014,8 @@ static void do_level_update_objects() {
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag = 0;
// g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
screen_unk5();
// g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40;
@ -2034,10 +2029,10 @@ static void do_level_update_objects() {
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].unk63 = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].unk63 = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].restart_level_flag = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].restart_level_flag = 0;
g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag = 0;
g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag = 0;
screen_vsync();
}
if (g_vars.objects[35].screen_ypos > 90) {

View File

@ -7,7 +7,8 @@
struct resource_data_t g_res;
void res_init(int vga_size) {
void res_init(const char *datapath, int vga_size) {
fio_init(datapath);
static const int SQL_SIZE = 640 * 25;
g_res.sql = (uint8_t *)malloc(SQL_SIZE);
if (!g_res.sql) {
@ -56,6 +57,7 @@ void res_init(int vga_size) {
}
void res_fini() {
fio_fini();
free(g_res.sql);
g_res.sql = 0;
free(g_res.spr_sqv);
@ -102,7 +104,7 @@ static void copy_cga(uint8_t *dst, int dst_pitch, uint8_t *dither_lut) {
for (int y = 0; y < 200; ++y) {
const uint8_t *p = dither_lut + (y & 1) * 0x10;
for (int x = 0; x < 320; ++x) {
dst[x] = p[dst[x]] & 3;
dst[x] = p[dst[x]];
}
dst += dst_pitch;
}
@ -280,9 +282,6 @@ void load_ck(const char *filename, uint16_t offset, int dither_pattern) {
break;
}
load_iff(g_res.tmp, size, g_res.tiles + offset, 640, dither_pattern);
if (dither_pattern < 0) {
g_sys.set_screen_palette(g_res.palette, 16);
}
}
void load_img(const char *filename, int screen_w, int dither_pattern) {
@ -294,12 +293,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.tmp + 32000, screen_w, dither_pattern);
load_iff(g_res.tmp, size, g_res.vga, screen_w, dither_pattern);
if (dither_pattern < 0) {
g_sys.set_screen_palette(g_res.palette, 16);
g_sys.set_screen_palette(g_res.palette, 0, 16, 8);
}
g_sys.update_screen(g_res.tmp + 32000, 0);
memcpy(g_res.vga, g_res.tmp + 32000, g_res.vga_size);
g_sys.update_screen(g_res.vga, 0);
}
void load_m(const char *filename) {

View File

@ -12,7 +12,7 @@ struct trigger_t {
int16_t tile_type;
int16_t tile_flags;
uint8_t op_func;
const uint8_t *op_table1; // dy for (x&15)
const uint8_t *op_table1; // tile_yoffset
const uint8_t *op_table2; // tile_animation
int16_t unk10;
const uint8_t *op_table3; // tile_trigger
@ -51,7 +51,7 @@ struct resource_data_t {
extern struct resource_data_t g_res;
extern void res_init(int vga_size);
extern void res_init(const char *datapath, int vga_size);
extern void res_fini();
extern int read_file(const char *filename, uint8_t *dst, int size);
extern int read_compressed_file(const char *filename, uint8_t *dst);

View File

@ -56,7 +56,7 @@ void screen_adjust_palette_color(int color, int b, int c) {
if (!g_options.cga_colors) {
g_res.palette[color * 3 + b] += c;
screen_vsync();
g_sys.set_screen_palette(g_res.palette, 16);
g_sys.set_screen_palette(g_res.palette, 0, 16, 8);
}
}
@ -90,24 +90,20 @@ void screen_flip() {
g_sys.update_screen(g_res.vga, 1);
}
void screen_copy_img() {
memcpy(g_res.vga, g_res.tmp + 32000, GAME_SCREEN_W * GAME_SCREEN_H);
}
void screen_unk5() {
// screen_do_transition2();
screen_clear(0);
}
void screen_do_transition1(int a) {
print_warning("screen_do_transition1 %d", a);
// print_warning("screen_do_transition1 %d", a);
if (a) {
g_sys.transition_screen(TRANSITION_CURTAIN, true);
}
}
void screen_do_transition2() {
print_warning("screen_do_transition2");
// print_warning("screen_do_transition2");
g_sys.transition_screen(TRANSITION_SQUARE, true);
}
@ -207,7 +203,7 @@ static void dither_graphics(uint8_t *dst, int dst_pitch, int w, int h, const uin
if (color == 0) {
dst[x] = color_key;
} else {
dst[x] = p[color] & 3;
dst[x] = p[color];
}
}
dst += dst_pitch;
@ -232,7 +228,6 @@ static void decode_graphics(int spr_type, int start, int end, const uint8_t *dit
}
const int h = READ_LE_UINT16(ptr - 4);
const int w = READ_LE_UINT16(ptr - 2);
const int j = i - start;
if (current_x + w > MAX_SPRITESHEET_W) {
current_y += max_h;
if (current_x > max_w) {
@ -249,6 +244,7 @@ static void decode_graphics(int spr_type, int start, int end, const uint8_t *dit
if (dither_lut) {
dither_graphics(data + current_y * MAX_SPRITESHEET_W + current_x, MAX_SPRITESHEET_W, w, h, dither_lut, color_key);
}
const int j = i - start;
r[j].x = current_x;
r[j].y = current_y;
r[j].w = w;

View File

@ -145,9 +145,9 @@ void play_music(int num) {
}
}
_mpf = ModPlug_Load(buf, size);
}
free(buf);
}
}
fio_close(slot);
} else { // ExoticA
filename = _modules[num * 2 + 1];

View File

@ -12,9 +12,7 @@ uint16_t triggers_get_tile_type(int x, int y) {
}
uint16_t triggers_get_next_tile_flags(int x, int y) {
const uint8_t *p = lookup_sql(x, y);
int num = p[0];
num = g_res.triggers[num].unk16;
const int num = triggers_get_next_tile_num(x, y);
return g_res.triggers[num].tile_flags;
}
@ -470,7 +468,7 @@ static void trigger_func_op30(struct object_t *obj) {
static void trigger_func_op31(struct object_t *obj) {
if (obj->yvelocity > 0 && obj->unk2B == 0) {
obj->yvelocity = 0;
obj->ypos = (obj->ypos & ~15) + triggers_get_dy(obj);
obj->ypos = (obj->ypos & ~15) + triggers_tile_get_yoffset(obj);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
obj->sprite_type = 1;
@ -482,7 +480,7 @@ static void trigger_func_op31(struct object_t *obj) {
static void trigger_func_op32(struct object_t *obj) {
if (obj->yvelocity > 0 && obj->unk2B == 0) {
obj->yvelocity = 0;
obj->ypos = (obj->ypos & ~15) + triggers_get_dy(obj);
obj->ypos = (obj->ypos & ~15) + triggers_tile_get_yoffset(obj);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
obj->sprite_type = 1;
@ -508,7 +506,7 @@ static void trigger_func_op33(struct object_t *obj) {
static void trigger_func_op34(struct object_t *obj) {
if (obj->yvelocity > 0 && obj->unk2B == 0) {
obj->yvelocity = 0;
obj->ypos = (obj->ypos & ~15) + triggers_get_dy(obj);
obj->ypos = (obj->ypos & ~15) + triggers_tile_get_yoffset(obj);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
obj->sprite_type = 1;
@ -534,7 +532,7 @@ static void trigger_func_op35(struct object_t *obj) {
static void trigger_func_op36(struct object_t *obj) {
if (obj->yvelocity > 0 && obj->unk2B == 0) {
obj->yvelocity = 0;
obj->ypos = (obj->ypos & ~15) + triggers_get_dy(obj);
obj->ypos = (obj->ypos & ~15) + triggers_tile_get_yoffset(obj);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
obj->sprite_type = 4;
@ -556,7 +554,7 @@ static void trigger_func_op37(struct object_t *obj) {
static void trigger_func_op38(struct object_t *obj) {
if (obj->yvelocity > 0 && obj->unk2B == 0) {
obj->yvelocity = 0;
obj->ypos = (obj->ypos & ~15) + triggers_get_dy(obj);
obj->ypos = (obj->ypos & ~15) + triggers_tile_get_yoffset(obj);
obj->ypos16 = obj->ypos >> 4;
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
obj->sprite_type = 4;
@ -599,7 +597,7 @@ static void trigger_func_op40(struct object_t *obj) {
if (counter == 400) {
if (!g_vars.two_players_flag) {
g_vars.level_completed_flag = 1;
} else if (g_vars.objects[OBJECT_NUM_PLAYER1].flag_end_level != 0 && g_vars.objects[OBJECT_NUM_PLAYER2].flag_end_level != 0) {
} else if (g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0 && g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag != 0) {
g_vars.level_completed_flag = 1;
}
}
@ -764,9 +762,9 @@ void triggers_update_tiles1(struct object_t *obj) {
}
if (p[8] != 0) {
if (obj->data5F == g_vars.level + 1) { // music instrument must have been found to complete the level
if (obj->flag_end_level == 0) {
if (obj->level_complete_flag == 0) {
play_sound(SOUND_13);
obj->flag_end_level = 1;
obj->level_complete_flag = 1;
if (_di == 0) {
do_level_update_tile(obj->xpos16, obj->ypos16, p[2]);
} else {
@ -784,10 +782,8 @@ void triggers_update_tiles1(struct object_t *obj) {
}
g_vars.triggers_counter = 0;
}
} else if (g_vars.triggers_counter == 0) {
g_vars.triggers_counter = 1;
}
} else {
if (_di == 0) {
@ -890,7 +886,7 @@ void triggers_update_tiles1(struct object_t *obj) {
}
}
int16_t triggers_get_dy(struct object_t *obj) {
int16_t triggers_tile_get_yoffset(struct object_t *obj) {
const uint8_t *p = lookup_sql(obj->xpos16, obj->ypos16);
const int num = p[0];
return g_res.triggers[num].op_table1[obj->xpos & 15] - 1;

BIN
bbja1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
bbja2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -9,20 +9,58 @@
#include <string.h>
#include <stdbool.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
#endif
#define SWAP(x, y) do { typeof(x) tmp = x; x = y; y = tmp; } while(0)
static inline uint16_t READ_BE_UINT16(const uint8_t *p) {
return (p[0] << 8) | p[1];
#undef MIN
static inline int MIN(int a, int b) {
return (a < b) ? a : b;
}
#undef MAX
static inline int MAX(int a, int b) {
return (a > b) ? a : b;
}
static inline uint32_t READ_BE_UINT32(const uint8_t *p) {
return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
}
static inline uint16_t READ_BE_UINT16(const uint8_t *p) {
return (p[0] << 8) | p[1];
}
static inline uint16_t READ_LE_UINT16(const uint8_t *p) {
return p[0] | (p[1] << 8);
}
static inline void WRITE_LE_UINT16(uint8_t *p, uint16_t value) {
p[0] = value & 0xFF;
p[1] = value >> 8;
}
#define GAME_SCREEN_W g_options.screen_w
#define GAME_SCREEN_H g_options.screen_h
struct options_t {
uint32_t cheats;
int start_level;
int start_xpos16;
int start_ypos16;
int screen_w;
int screen_h;
// 'bb' only options
bool amiga_copper_bars;
bool amiga_colors;
bool amiga_status_bar;
bool dos_scrolling;
bool cga_colors;
};
struct game_t {
const char *name;
//int (*detect)(const char *data_path);
void (*run)(const char *data_path);
};
#endif

361
ja/game.c Normal file
View File

@ -0,0 +1,361 @@
/* game screens */
#include "game.h"
#include "resource.h"
#include "sys.h"
struct vars_t g_vars;
void update_input() {
g_sys.process_events();
g_vars.input_key_left = (g_sys.input.direction & INPUT_DIRECTION_LEFT) != 0 ? 0xFF : 0;
g_vars.input_key_right = (g_sys.input.direction & INPUT_DIRECTION_RIGHT) != 0 ? 0xFF : 0;
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_keystate[2] = g_sys.input.digit1;
g_vars.input_keystate[3] = g_sys.input.digit2;
g_vars.input_keystate[4] = g_sys.input.digit3;
}
static void wait_input(int timeout) {
const uint32_t end = g_sys.get_timestamp() + timeout * 10;
while (g_sys.get_timestamp() < end) {
g_sys.process_events();
if (g_sys.input.quit || g_sys.input.space) {
break;
}
g_sys.sleep(20);
}
}
static void do_splash_screen() {
load_file("titus.eat");
video_copy_vga(0x7D00);
fade_in_palette();
fade_out_palette();
load_file("tiny.eat");
video_copy_vga(0x7D00);
fade_in_palette();
fade_out_palette();
}
static void scroll_screen_palette() {
g_vars.level_time += 3;
if (g_vars.level_time >= 90) {
g_vars.level_time = 0;
}
const int count = 90 - g_vars.level_time;
for (int i = 0; i < count; i += 3) {
g_sys.set_palette_color(225 + i / 3, g_res.tmp + 225 * 3 + g_vars.level_time + i);
}
g_sys.update_screen(g_res.vga, 1);
}
static void do_select_screen_scroll_palette(int start, int end, int step, int count) {
uint8_t *palette_buffer = g_res.tmp;
do {
for (int i = start * 3; i < end * 3; ++i) {
int color = g_vars.palette_buffer[i];
if ((step > 0 && color != palette_buffer[i]) || (step < 0 && color != 0)) {
color += step;
}
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.sleep(20);
} while (--count != 0);
}
static void do_select_screen_scroll_palette_pattern1() {
do_select_screen_scroll_palette(0x10, 0x4F, -1, 0x19);
}
static void do_select_screen_scroll_palette_pattern2() {
do_select_screen_scroll_palette(0x60, 0x9F, -1, 0x19);
}
static void do_select_screen_scroll_palette_pattern3() {
do_select_screen_scroll_palette(0x10, 0x4F, 1, 0x19);
}
static void do_select_screen_scroll_palette_pattern4() {
do_select_screen_scroll_palette(0x60, 0x9F, 1, 0x19);
}
static void do_select_screen() {
load_file("select.eat");
video_copy_vga(0x7D00);
fade_in_palette();
memcpy(g_vars.palette_buffer, g_res.tmp, 256 * 3);
do_select_screen_scroll_palette_pattern2();
int bl = 2;
while (!g_sys.input.quit) {
int bh = bl;
video_vsync(60);
if (g_sys.input.direction & INPUT_DIRECTION_RIGHT) {
g_sys.input.direction &= ~INPUT_DIRECTION_RIGHT;
++bl;
bl &= 3;
if (bl == 0) {
bl = 1;
}
video_vsync(60);
}
if (g_sys.input.direction & INPUT_DIRECTION_LEFT) {
g_sys.input.direction &= ~INPUT_DIRECTION_LEFT;
--bl;
bl &= 3;
if (bl == 0) {
bl = 3;
}
video_vsync(60);
}
bh ^= bl;
if (bh & 1) {
if (bl & 1) {
do_select_screen_scroll_palette_pattern4();
} else {
do_select_screen_scroll_palette_pattern2();
}
}
if (bh & 2) {
if (bl & 2) {
do_select_screen_scroll_palette_pattern3();
} else {
do_select_screen_scroll_palette_pattern1();
}
}
if (g_sys.input.space) {
assert(bl == 1 || bl == 2);
g_sys.input.space = 0;
g_vars.player = 1 - ((bl & 3) - 1);
fade_out_palette();
break;
}
update_input();
g_sys.sleep(30);
}
}
void do_difficulty_screen() {
char name[16];
snprintf(name, sizeof(name), "dif%02d.eat", (g_vars.level >> 3) + 1);
load_file(name);
video_copy_vga(0x7D00);
fade_in_palette();
wait_input(560);
fade_out_palette();
}
void do_level_number_screen() {
load_file("fond.eat");
video_draw_string("LEVEL NUMBER", 0x5E0C, 11);
char buf[8];
snprintf(buf, sizeof(buf), "%02d", g_vars.level);
video_draw_string(buf, 0x5E9B, 11);
video_copy_vga(0x7D00);
fade_in_palette();
fade_out_palette();
}
static uint16_t get_password(uint16_t ax) {
// ax = read(0xF000:0xFFFF, 16) // bios
ax ^= 0xAA31;
// rol ax, cpu_speed
return ax;
}
void do_level_password_screen() {
load_file("password.eat");
uint16_t ax = get_password(g_vars.player * 50 + g_vars.level - 1);
char str[5];
for (int i = 0; i < 4; ++i, ax <<= 4) {
static const uint8_t rev_bits[] = {
0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF
};
const uint8_t dx = rev_bits[(ax >> 15) & 15] + '0';
str[i] = (dx <= '9') ? dx : (dx + 7);
}
str[4] = 0;
video_draw_string("STAGE NUMBER", 0x7E96, 11);
video_draw_string(str, 0xABB4, 20);
video_copy_vga(0x7D00);
fade_in_palette();
scroll_screen_palette();
wait_input(64000);
fade_out_palette();
}
static void do_password_screen() {
load_file("password.eat");
video_draw_string("ENTER PASSWORD", 0x7E96, 11);
fade_in_palette();
char str[5] = "0000";
video_draw_string(str, 0xABB4, 20);
}
static int do_menu_screen() {
load_file("menu.eat");
video_copy_vga(0x7D00);
fade_in_palette();
memset(g_vars.input_keystate, 0, sizeof(g_vars.input_keystate));
g_vars.level_time = 0;
while (!g_sys.input.quit) {
scroll_screen_palette();
if (g_vars.input_keystate[2] || g_vars.input_keystate[0x4F] || g_sys.input.space) {
g_sys.input.space = 0;
fade_out_palette();
return 1;
}
if (g_vars.input_keystate[3] || g_vars.input_keystate[0x50]) {
fade_out_palette();
return 2;
}
if (g_vars.input_keystate[4] || g_vars.input_keystate[0x51]) {
return 3;
}
update_input();
g_sys.sleep(30);
}
return 0;
}
static int do_options_screen() {
fade_out_palette();
load_file("fond.eat");
video_draw_string("GAME SPEED", 0x3EE9, 11);
video_draw_string("1 FAST", 0x647E, 11);
video_draw_string("2 NORMAL", 0x89FE, 11);
video_copy_vga(0x7D00);
fade_in_palette();
memset(g_vars.input_keystate, 0, sizeof(g_vars.input_keystate));
while (!g_sys.input.quit) {
scroll_screen_palette();
if (g_vars.input_keystate[2] || g_vars.input_keystate[0x4F]) {
fade_out_palette();
return 1;
}
if (g_vars.input_keystate[3] || g_vars.input_keystate[0x50]) {
fade_out_palette();
return 2;
}
update_input();
g_sys.sleep(30);
}
return 0;
}
void do_game_over_screen() {
load_file("fond.eat");
video_draw_string("GAME OVER", 0x5E2E, 11);
video_copy_vga(0x7D00);
fade_in_palette();
wait_input(64000);
fade_out_palette();
}
void do_game_win_screen() {
load_file("win.eat");
video_copy_vga(0x7D00);
fade_in_palette();
fade_out_palette();
load_file("end.eat");
video_copy_vga(0x7D00);
static const int count = 5;
static const struct {
uint16_t offset;
const char *str;
} text[] = {
{ 0x0F68, "CONGRATULATION" },
{ 0x3B34, "YOU HAVE BEATEN" },
{ 0x5CE8, "THE EVIL JUKEBOXE" },
{ 0x7EB1, "NOW YOU ARE FREE" },
{ 0xA072, "AND YOUR CONCERT" },
{ 0xC22D, "WILL BE A SUCCESS" },
{ 0xFFFF, 0 },
{ 0x33BE, "PC CONVERSION" },
{ 0x5590, "ERIC ZMIRO" },
{ 0x864D, "PC GRAPHICS" },
{ 0xA7FC, "DIDIER CARRERE" },
{ 0xFFFF, 0 },
{ 0x33AF, "ORIGINAL VERSION" },
{ 0x5594, "ERIC CAEN" },
{ 0x862B, "ORIGINAL GRAPHICS" },
{ 0xA835, "BOB" },
{ 0xFFFF, 0 },
{ 0x33B1, "ORIGINAL MUSICS" },
{ 0x559A, "DIMITRI" },
{ 0x8653, "PC MUSICS" },
{ 0xA7F2, "MICHAEL KNAEPEN" },
{ 0xFFFF, 0 },
{ 0x5A8F, "THANK YOU" },
{ 0x8008, "FOR PLAYING" },
{ 0xFFFF, 0 }
};
int i = 0;
for (int j = 0; j < count; ++j) {
for (; text[i].str; ++i) {
video_draw_string(text[i].str, text[i].offset, 11);
}
++i;
video_copy_vga(0x7D00);
fade_in_palette();
wait_input(64000);
fade_out_palette();
video_copy_vga(0x7D00);
}
}
void game_main() {
play_music(0);
do_splash_screen();
g_sys.set_screen_palette(common_palette_data, 0, 128, 6);
video_load_sprites();
render_set_sprites_clipping_rect(0, 0, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H);
while (!g_sys.input.quit) {
update_input();
g_vars.level = g_options.start_level;
if (g_vars.level == 0) {
g_vars.level = 1;
}
const int ret = do_menu_screen();
g_vars.players_table[0].lifes_count = 3;
g_vars.players_table[1].lifes_count = 3;
if (ret == 0) {
break;
} else if (ret == 1) {
do_select_screen();
do_difficulty_screen();
} else if (ret == 2) {
g_vars.level = -1;
do_password_screen();
if (g_vars.level < 0) {
continue;
}
++g_vars.level;
do_difficulty_screen();
} else {
do_options_screen();
continue;
}
do_level();
}
}
static void game_run(const char *data_path) {
res_init(data_path, GAME_SCREEN_W * GAME_SCREEN_H);
sound_init();
game_main();
sound_fini();
res_fini();
}
struct game_t game = {
"Blues Brothers : Jukebox Adventure",
game_run
};

225
ja/game.h Normal file
View File

@ -0,0 +1,225 @@
#ifndef GAME_H__
#define GAME_H__
#include "intern.h"
#define CHEATS_OBJECT_NO_HIT (1 << 0)
#define CHEATS_ONE_HIT_VINYL (1 << 1)
#define CHEATS_DECOR_NO_HIT (1 << 2)
extern struct options_t g_options;
#define TILEMAP_SCREEN_W GAME_SCREEN_W
#define TILEMAP_SCREEN_H (GAME_SCREEN_H - PANEL_H)
#define PANEL_H 24
#define SOUND_0 0
#define SOUND_1 1 // monster knocked out
#define SOUND_2 2 // bouncing mushroom
#define SOUND_3 3 // decor hit
#define SOUND_4 4 // player hit
#define SOUND_5 5 // grab vinyl
#define SOUND_8 8 // no vinyl
#define SOUND_9 9 // throw vinyl
#define SOUND_10 10 // "rock,rock,rock and roll"
#define SOUND_11 11
#define SOUND_14 14 // player lost life
#define SOUND_15 15 // running out time
struct object_t {
int16_t x_pos;
int16_t y_pos;
uint16_t spr_num;
union {
uint8_t b[2];
int16_t w;
const uint8_t *p;
} data[11]; // 0x6..0x1C
};
enum {
PLAYER_FLAGS_STAIRS = 2,
PLAYER_FLAGS_FACING_LEFT = 4,
PLAYER_FLAGS_THROW_VINYL = 8,
PLAYER_FLAGS_POWERUP = 0x20,
PLAYER_FLAGS_JAKE = 0x80
};
#define player_obj_num(obj) (obj)->data[0].w // 0x6
#define player_prev_spr_num(obj) (obj)->data[1].w // 0x8
#define player_anim_data(obj) (obj)->data[2].p // 0xA
#define player_idle_counter(obj) (obj)->data[3].b[0] // 0xC
#define player_power(obj) (obj)->data[3].b[1] // 0xD
#define player_x_delta(obj) (obj)->data[4].w // 0xE
#define player_y_delta(obj) (obj)->data[5].w // 0x10
#define player_flags(obj) (obj)->data[6].b[0] // 0x12
#define player_jump_counter(obj) (obj)->data[6].b[1] // 0x13
#define player_bounce_counter(obj) (obj)->data[7].b[0] // 0x14
#define player_tilemap_offset(obj) (obj)->data[8].w // 0x16
#define player_hit_counter(obj) (obj)->data[9].b[0] // 0x18
#define player_throw_counter(obj) (obj)->data[9].b[1] // 0x19
#define player_flags2(obj) (obj)->data[10].b[0] // 0x1A, 8:dead 1:blocked
#define object_blinking_counter(obj) (obj)->data[6].b[1] // 0x13, shield, jump
// star
#define object2_spr_count(obj) (obj)->data[0].b[0]
#define object2_spr_tick(obj) (obj)->data[0].b[1]
// vinyl
#define object22_xvelocity(obj) (obj)->data[0].w
#define object22_damage(obj) (obj)->data[1].w
#define object22_player_num(obj) (obj)->data[2].w
// crate
#define object64_counter(obj) (obj)->data[1].w
#define object64_yvelocity(obj) (obj)->data[2].w
// monster
#define object82_state(obj) (obj)->data[0].b[0]
#define object82_type(obj) (obj)->data[0].b[1]
#define object82_anim_data(obj) (obj)->data[1].p
#define object82_hflip(obj) (obj)->data[3].b[0]
#define object82_counter(obj) (obj)->data[3].b[1]
#define object82_x_delta(obj) (obj)->data[4].w
#define object82_y_delta(obj) (obj)->data[5].w
#define object82_energy(obj) (obj)->data[8].w
#define object82_type0_init_data(obj) (obj)->data[4].p
#define object82_type0_player_num(obj) (obj)->data[5].w
#define object82_type0_x_delta(obj) (obj)->data[6].b[0] // signed
#define object82_type0_y_delta(obj) (obj)->data[7].b[0] // signed
#define object82_type1_hdir(obj) (obj)->data[6].b[0] // signed
#define object102_x_delta(obj) (obj)->data[0].w
#define object102_y_delta(obj) (obj)->data[1].w
struct player_t {
struct object_t obj;
int16_t unk_counter; // 0x1D always zero
int16_t change_hdir_counter;
uint8_t lifes_count;
int16_t vinyls_count;
int8_t energy;
uint8_t dir_mask; // 0x25
uint8_t ticks_counter; // 0x26
};
#define TRIGGERS_COUNT 36
#define LEVELS_COUNT 30
#define OBJECTS_COUNT 165
// offset | count | comment
// 2 20 animated tiles/vinyls
// 22 10 vinyls
// 32 8 * 4 (rotating) platforms
// 64 8 crates
// 72 10 bonuses spr_num:190
// 82 20 monsters
// 102 10
// 112 9 vertical bars
// 121 8 dragon monster (level 26)
struct vars_t {
int level;
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;
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];
uint8_t player_hit_counter;
int16_t player_xscroll, player_map_offset;
struct object_t objects_table[OBJECTS_COUNT];
int level_start_1p_x_pos, level_start_1p_y_pos;
int level_start_2p_player1_x_pos, level_start_2p_player1_y_pos, level_start_2p_player2_x_pos, level_start_2p_player2_y_pos;
int level_loop_counter;
int throw_vinyl_counter;
uint8_t level_num;
uint16_t level_time, level_time2;
uint8_t level_time_counter;
uint8_t triggers_table[19 + TRIGGERS_COUNT * 16];
int tilemap_x, tilemap_y, tilemap_w, tilemap_h;
int tilemap_end_x, tilemap_end_y;
int tilemap_scroll_dx, tilemap_scroll_dy, tilemap_scroll_xoffset, tilemap_scroll_yoffset;
uint8_t *tilemap_data;
uint16_t level_pos_num;
uint8_t tilemap_type, tilemap_flags;
uint8_t tilemap_lut_type[0x100]; // type:0,1,2
uint8_t tilemap_lut_init[6 * 0x100];
uint8_t tilemap_lut_init2[0x100];
const uint8_t *tilemap_current_lut;
uint8_t tile_palette_table[0x100];
const uint8_t *level_tiles_lut;
uint8_t palette_buffer[256 * 3];
bool change_next_level_flag;
bool reset_palette_flag;
};
extern struct vars_t g_vars;
/* staticres.c */
extern const uint16_t sound_offsets[];
extern const uint16_t sprite_offsets[];
extern const uint16_t sprite_sizes[];
extern const uint8_t sprite_palettes[];
extern const uint8_t level_data1p[];
extern const uint8_t level_data2p[];
extern const uint8_t level_data3[];
extern const uint8_t level_data4[];
extern const uint8_t monster_spr_anim_data0[];
extern const uint8_t monster_spr_anim_data1[];
extern const uint8_t monster_spr_anim_data2[];
extern const uint8_t monster_spr_anim_data3[];
extern const uint8_t monster_spr_anim_data4[];
extern const uint8_t monster_spr_anim_data6[];
extern const uint8_t monster_spr_anim_data8[];
extern const uint8_t monster_spr_anim_data9[];
extern const uint8_t common_palette_data[];
extern const uint8_t levels_palette_data[];
extern const uint8_t tile_lut_data0[];
extern const uint8_t tile_lut_data1[];
extern const uint8_t tile_lut_data2[];
extern const uint8_t tile_lut_data3[];
extern const uint16_t tile_funcs0[];
extern const uint16_t tile_funcs1[];
extern const uint16_t tile_funcs2[];
extern const uint16_t tile_funcs3[];
extern const uint8_t level_data_tiles_lut[];
extern const uint8_t player_anim_dy[];
extern const uint8_t player_anim_lut[];
extern const uint8_t *player_anim_table[];
/* game.c */
extern void update_input();
extern void game_main();
extern void do_game_over_screen();
extern void do_game_win_screen();
extern void do_difficulty_screen();
extern void do_level_password_screen();
extern void do_level_number_screen();
/* level.c */
extern void do_level();
/* screen.c */
extern void video_draw_dot_pattern(int offset);
extern void video_draw_sprite(int num, int x, int y, int flag);
extern void video_draw_string(const char *s, int offset, int hspace);
extern void video_copy_vga(int size);
extern void video_vsync(int delay);
extern void fade_in_palette();
extern void fade_out_palette();
extern void ja_decode_spr(const uint8_t *src, int w, int h, uint8_t *dst, int dst_pitch, uint8_t pal_mask);
extern void ja_decode_chr(const uint8_t *buffer, const int size, uint8_t *dst, int dst_pitch);
extern void ja_decode_tile(const uint8_t *buffer, uint8_t pal_mask, uint8_t *dst, int dst_pitch, int x, int y);
extern void video_load_sprites();
/* sound.c */
extern void sound_init();
extern void sound_fini();
extern void play_sound(int num);
extern void play_music(int num);
#endif /* GAME_H__ */

3039
ja/level.c Normal file

File diff suppressed because it is too large Load Diff

88
ja/resource.c Normal file
View File

@ -0,0 +1,88 @@
#include <sys/param.h>
#include "resource.h"
#include "unpack.h"
#include "util.h"
static const int TMP_SIZE = 72728;
static const int BACKGROUND_SIZE = 320 * 200;
static const char *_datapath;
struct resource_t g_res;
void res_init(const char *path, int vga_size) {
_datapath = path;
char filepath[MAXPATHLEN];
static const int FONT_SIZE = 7264;
g_res.font = (uint8_t *)malloc(FONT_SIZE);
if (!g_res.font) {
print_error("Failed to allocate font buffer, %d bytes", FONT_SIZE);
}
snprintf(filepath, sizeof(filepath), "%s/font256.eat", _datapath);
unpack(filepath, g_res.font, FONT_SIZE);
static const int BOARD_SIZE = 12800;
g_res.board = (uint8_t *)malloc(BOARD_SIZE);
if (!g_res.board) {
print_error("Failed to allocate board buffer, %d bytes", BOARD_SIZE);
}
snprintf(filepath, sizeof(filepath), "%s/board.eat", _datapath);
unpack(filepath, g_res.board, BOARD_SIZE);
static const int SPRITES_SIZE = 108044;
g_res.sprites = (uint8_t *)malloc(SPRITES_SIZE);
if (!g_res.sprites) {
print_error("Failed to allocate sprites buffer, %d bytes", SPRITES_SIZE);
}
snprintf(filepath, sizeof(filepath), "%s/sprites.eat", _datapath);
unpack(filepath, g_res.sprites, SPRITES_SIZE);
static const int SAMPLES_SIZE = 49398;
g_res.samples = (uint8_t *)malloc(SAMPLES_SIZE);
if (!g_res.samples) {
print_error("Failed to allocate samples buffer, %d bytes", SAMPLES_SIZE);
}
snprintf(filepath, sizeof(filepath), "%s/samples.eat", _datapath);
unpack(filepath, g_res.samples, SAMPLES_SIZE);
g_res.tmp = (uint8_t *)malloc(TMP_SIZE);
if (!g_res.tmp) {
print_error("Failed to allocate tmp buffer, %d bytes", TMP_SIZE);
}
g_res.background = (uint8_t *)malloc(BACKGROUND_SIZE);
if (!g_res.background) {
print_error("Failed to allocate tmp buffer, %d bytes", BACKGROUND_SIZE);
}
g_res.vga = (uint8_t *)malloc(vga_size);
if (!g_res.vga) {
print_error("Failed to allocate vga buffer, %d bytes", vga_size);
}
}
void res_fini() {
free(g_res.font);
g_res.font = 0;
free(g_res.board);
g_res.board = 0;
free(g_res.sprites);
g_res.sprites = 0;
free(g_res.tmp);
g_res.tmp = 0;
free(g_res.background);
g_res.background = 0;
free(g_res.vga);
g_res.vga = 0;
}
int load_file(const char *filename) {
char filepath[MAXPATHLEN];
snprintf(filepath, sizeof(filepath), "%s/%s", _datapath, filename);
print_debug(DBG_RESOURCE, "load_file '%s'", filepath);
return unpack(filepath, g_res.tmp, TMP_SIZE);
}

23
ja/resource.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef RESOURCE_H__
#define RESOURCE_H__
#include "intern.h"
struct resource_t {
uint8_t *font;
uint8_t *board;
uint8_t *sprites;
uint8_t *samples;
uint8_t *tmp;
uint8_t *background;
uint8_t *vga;
};
extern struct resource_t g_res;
extern void res_init(const char *datapath, int vga_size);
extern void res_fini();
extern int load_file(const char *filename);
#endif

225
ja/screen.c Normal file
View File

@ -0,0 +1,225 @@
/* screen drawing */
#include "game.h"
#include "resource.h"
#include "sys.h"
#include "util.h"
#define MAX_SPRITES 288
#define MAX_SPRITESHEET_W 1024
#define MAX_SPRITESHEET_H 512
void video_draw_dot_pattern(int offset) {
static const int W = 144;
uint8_t *dst = g_res.vga + (GAME_SCREEN_H - PANEL_H) * GAME_SCREEN_W + offset;
for (int y = 0; y < PANEL_H; ++y) {
for (int x = 0; x < W; x += 2) {
dst[x + (y & 1)] = 0;
}
dst += GAME_SCREEN_W;
}
}
void video_draw_sprite(int num, int x, int y, int flag) {
render_add_sprite(RENDER_SPR_GAME, num, x, y, flag != 0);
}
void video_draw_string(const char *s, int offset, int hspace) {
while (*s) {
uint8_t code = *s++;
if (code != 0x20) {
if (code >= 0x41) {
code -= 0x41;
} else {
code -= 0x16;
}
ja_decode_chr(g_res.font + code * 200, 200, g_res.tmp + 768 + offset, 320);
}
offset += hspace;
}
}
void video_copy_vga(int size) {
if (size == 0xB500) {
memcpy(g_res.background, g_res.tmp + 768, 64000);
} else {
g_sys.set_screen_palette(g_res.tmp, 0, 256, 6);
assert(size == 0x7D00);
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);
}
}
void video_vsync(int delay) {
}
void fade_in_palette() {
if (!g_sys.input.quit) {
g_sys.fade_in_palette();
}
}
void fade_out_palette() {
if (!g_sys.input.quit) {
g_sys.fade_out_palette();
}
}
void ja_decode_spr(const uint8_t *src, int w, int h, uint8_t *dst, int dst_pitch, uint8_t pal_mask) {
const int bitplane_size = w * h;
for (int y = 0; y < h; ++y) {
for (int x = 0; x < w; ++x) {
for (int i = 0; i < 8; ++i) {
int color = 0;
const int mask = 1 << (7 - i);
for (int bit = 0; bit < 4; ++bit) {
if (src[bit * bitplane_size] & mask) {
color |= 1 << bit;
}
}
if (color != 0) {
dst[x * 8 + i] = pal_mask | color;
}
}
++src;
}
dst += dst_pitch;
}
}
void ja_decode_chr(const uint8_t *buffer, const int size, uint8_t *dst, int dst_pitch) {
for (int y = 0; y < 25; ++y) {
const int offset = y * 2;
const uint16_t p[] = {
READ_BE_UINT16(buffer + offset),
READ_BE_UINT16(buffer + offset + 50),
READ_BE_UINT16(buffer + offset + 100),
READ_BE_UINT16(buffer + offset + 150)
};
for (int x = 0; x < 16; ++x) {
const uint16_t mask = 1 << (15 - x);
uint8_t color = 0;
for (int b = 0; b < 4; ++b) {
if (p[b] & mask) {
color |= (1 << b);
}
}
if (color != 0) {
dst[x] = 0xD0 | color;
}
}
dst += dst_pitch;
}
}
void ja_decode_tile(const uint8_t *buffer, uint8_t pal_mask, uint8_t *dst, int dst_pitch, int x_offset, int y_offset) {
int tile_w = 16;
if (x_offset < 0) {
tile_w += x_offset;
buffer -= x_offset / 2;
x_offset = 0;
}
if (x_offset + tile_w > TILEMAP_SCREEN_W) {
tile_w = TILEMAP_SCREEN_W - x_offset;
}
if (tile_w <= 0) {
return;
}
int tile_h = 16;
if (y_offset < 0) {
tile_h += y_offset;
buffer -= y_offset * 8;
y_offset = 0;
}
if (y_offset + tile_h > TILEMAP_SCREEN_H) {
tile_h = TILEMAP_SCREEN_H - y_offset;
}
if (tile_h <= 0) {
return;
}
dst += y_offset * dst_pitch + x_offset;
for (int y = 0; y < tile_h; ++y) {
uint8_t *p = dst;
for (int x = 0; x < tile_w / 2; ++x) {
const uint8_t color1 = buffer[x] >> 4;
const uint8_t color2 = buffer[x] & 15;
if (color1 != 0) {
*p = pal_mask | color1;
}
++p;
if (color2 != 0) {
*p = pal_mask | color2;
}
++p;
}
buffer += 8;
dst += dst_pitch;
}
}
void video_load_sprites() {
struct sys_rect_t r[MAX_SPRITES];
uint8_t *data = (uint8_t *)calloc(MAX_SPRITESHEET_W * MAX_SPRITESHEET_H, 1);
if (data) {
int current_x = 0;
int max_w = 0;
int current_y = 0;
int max_h = 0;
int total_size = 0;
int count = 0;
uint8_t value;
for (int i = 0; (value = sprite_offsets[i] & 255) != 0; ++i, ++count) {
value = (value >> 3) | ((value & 7) << 5);
if ((value & 0xE0) != 0) {
value &= ~0xE0;
++value;
}
const int h = sprite_offsets[i] >> 8;
const int w = value * 8;
assert((sprite_offsets[i] & 255) == w);
const int size = (h * value) * 4;
if (current_x + w > MAX_SPRITESHEET_W) {
current_y += max_h;
if (current_x > max_w) {
max_w = current_x;
}
current_x = 0;
max_h = h;
} else {
if (h > max_h) {
max_h = h;
}
}
ja_decode_spr(g_res.sprites + total_size, w / 8, h, data + current_y * MAX_SPRITESHEET_W + current_x, MAX_SPRITESHEET_W, sprite_palettes[i] * 0x10);
total_size += size;
r[i].x = current_x;
r[i].y = current_y;
r[i].w = w;
r[i].h = h;
current_x += w;
if (h > max_h) {
max_h = h;
}
}
assert(count <= MAX_SPRITES);
assert(max_w <= MAX_SPRITESHEET_W);
assert(current_y + max_h <= MAX_SPRITESHEET_H);
render_unload_sprites(RENDER_SPR_GAME);
render_load_sprites(RENDER_SPR_GAME, count, r, data, MAX_SPRITESHEET_W, current_y + max_h, 0, 0x0);
free(data);
}
}

123
ja/sound.c Normal file
View File

@ -0,0 +1,123 @@
#include "game.h"
#include "resource.h"
#include "sys.h"
#include "util.h"
#include <libmodplug/modplug.h>
#define MAX_SOUNDS 16
static const char *_modules[] = {
"almost.mod",
"every.mod",
"bartende.mod",
"petergun.mod",
"shoot.mod"
};
struct mixerchannel_t {
uint8_t *data;
uint32_t pos;
uint32_t step;
uint32_t size;
const int8_t *seq;
};
static struct {
uint16_t offset;
uint16_t size;
} _samples[MAX_SOUNDS];
static const int _rate = SYS_AUDIO_FREQ;
static struct mixerchannel_t _channel;
static ModPlugFile *_mpf;
static void mix(void *param, uint8_t *buf, int len) {
memset(buf, 0, len);
if (_mpf) {
const int count = ModPlug_Read(_mpf, buf, len);
if (count == 0) {
ModPlug_SeekOrder(_mpf, 0);
}
}
if (_channel.data) {
for (int i = 0; i < len; i += sizeof(int16_t)) {
int pos = _channel.pos >> 16;
if (pos >= _channel.size) {
const int next = _channel.seq ? *_channel.seq++ : -1;
if (next < 0) {
_channel.data = 0;
break;
}
_channel.data = g_res.samples + _samples[next].offset;
_channel.pos = pos = 0;
_channel.size = _samples[next].size;
}
const int sample = *(int16_t *)(buf + i) + ((int8_t)_channel.data[pos]) * 256;
*(int16_t *)(buf + i) = (sample < -32768 ? -32768 : (sample > 32767 ? 32767 : sample));
_channel.pos += _channel.step;
}
}
}
void sound_init() {
ModPlug_Settings mp_settings;
memset(&mp_settings, 0, sizeof(mp_settings));
ModPlug_GetSettings(&mp_settings);
mp_settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING | MODPLUG_ENABLE_NOISE_REDUCTION;
mp_settings.mChannels = 1;
mp_settings.mBits = 16;
mp_settings.mFrequency = _rate;
mp_settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;
mp_settings.mLoopCount = -1;
ModPlug_SetSettings(&mp_settings);
g_sys.start_audio(mix, 0);
uint16_t offset = 0;
for (int i = 0; i < MAX_SOUNDS; ++i) {
const int num = i;
_samples[i].size = sound_offsets[num];
_samples[i].offset = offset;
offset += _samples[i].size;
}
}
void sound_fini() {
g_sys.stop_audio();
}
void play_sound(int num) {
assert(num < MAX_SOUNDS);
const int sample_offset = _samples[num].offset;
const int sample_size = _samples[num].size;
print_debug(DBG_MIXER, "sample num %d offset 0x%x size %d", num, sample_offset, sample_size);
if (sample_size == 0) {
return;
}
g_sys.lock_audio();
_channel.data = g_res.samples + sample_offset;
_channel.pos = 0;
_channel.step = (8000 << 16) / _rate;
_channel.size = sample_size;
if (num == 10) {
static const int8_t seq[] = { 10, 10, 10, 6, -1 };
_channel.seq = seq + 1;
} else {
_channel.seq = 0;
}
g_sys.unlock_audio();
}
void play_music(int num) {
g_sys.lock_audio();
if (_mpf) {
ModPlug_Unload(_mpf);
_mpf = 0;
}
const int size = load_file(_modules[num]);
_mpf = ModPlug_Load(g_res.tmp, size);
if (_mpf) {
print_debug(DBG_MIXER, "Loaded module '%s'", ModPlug_GetName(_mpf));
}
g_sys.unlock_audio();
}

670
ja/staticres.c Normal file
View File

@ -0,0 +1,670 @@
#include "intern.h"
const uint16_t sound_offsets[] = {
0x04CA,0x185C,0x0F4C,0x05EC,0x0762,0x0898,0x1188,0x0000,0x0CC4,0x1378,0x089C,0x0606,0x0000,0x0000,0x1254,0x2BE4
};
const uint16_t sprite_offsets[] = {
0x2510,0x2420,0x2518,0x2518,0x2420,0x2518,0x1C18,0x1528,0x1528,0x1420,0x2618,0x2620,0x2420,0x2818,0x2318,0x2320,
0x1F28,0x2418,0x2320,0x2128,0x2418,0x2418,0x2418,0x1820,0x1E20,0x2620,0x2720,0x2718,0x2618,0x2718,0x2720,0x2520,
0x2A18,0x2020,0x1A20,0x2820,0x2820,0x1E20,0x2520,0x2520,0x2520,0x1C28,0x1010,0x1010,0x1010,0x1010,0x1010,0x0F10,
0x0808,0x0A08,0x2018,0x2010,0x1F18,0x2010,0x2018,0x1E20,0x1620,0x1720,0x1620,0x1620,0x2218,0x1E18,0x1F18,0x2218,
0x1E18,0x1E20,0x1E28,0x1F20,0x1C18,0x2220,0x1F18,0x1F18,0x1F18,0x1420,0x1820,0x2018,0x2118,0x2120,0x2020,0x2120,
0x2118,0x2120,0x2518,0x1C20,0x1B20,0x2420,0x2220,0x1B20,0x2120,0x2120,0x2120,0x1D20,0x0F10,0x1018,0x1010,0x1010,
0x0A10,0x0610,0x0608,0x0808,0x0910,0x0B10,0x0B10,0x0A08,0x0C10,0x0C10,0x0C10,0x0D10,0x0E10,0x0D10,0x0C10,0x0D10,
0x0E10,0x0E10,0x0E10,0x0C10,0x2D20,0x2D28,0x3330,0x2F38,0x2A30,0x2328,0x2128,0x2420,0x2320,0x2418,0x2528,0x2720,
0x2D30,0x2D30,0x2D30,0x2A30,0x2028,0x1D28,0x1F20,0x2020,0x1F18,0x2028,0x2320,0x1E18,0x2218,0x2318,0x2318,0x2220,
0x2318,0x2318,0x2518,0x2418,0x2220,0x1C18,0x2218,0x2218,0x2218,0x2718,0x2818,0x2820,0x2720,0x2820,0x2818,0x2920,
0x2920,0x2120,0x2820,0x2820,0x2720,0x1918,0x1A18,0x1A18,0x1918,0x1A18,0x1A18,0x1C18,0x1C18,0x1818,0x1720,0x1A18,
0x1A18,0x1A18,0x2020,0x2120,0x2120,0x2018,0x2120,0x2120,0x2420,0x2220,0x1D20,0x2120,0x2120,0x2220,0x0F10,0x0C10,
0x0610,0x0F10,0x0D10,0x1010,0x1010,0x1010,0x3028,0x2030,0x2020,0x0E08,0x0D10,0x2010,0x1010,0x1040,0x1D20,0x1B30,
0x1A20,0x1920,0x1D20,0x1D20,0x1F28,0x1D20,0x1718,0x1518,0x1518,0x1828,0x1628,0x1628,0x2828,0x0828,0x0A28,0x0A28,
0x2020,0x0B30,0x1830,0x1F20,0x1F10,0x1828,0x2428,0x2528,0x1F28,0x1010,0x0D10,0x0808,0x1D30,0x1E30,0x2030,0x2030,
0x1618,0x1718,0x1040,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F08,0x0F10,0x0F10,0x0F10,0x0F10,
0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F08,0x0F10,0x0408,
0x0410,0x0F10,0x0F08,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0F10,0x0000
};
const uint16_t sprite_sizes[] = {
0x2508,0x2410,0x250C,0x250C,0x2410,0x250C,0x1C0C,0x1514,0x1514,0x1410,0x260C,0x2610,0x2410,0x280C,0x270D,0x2310,
0x1F14,0x240E,0x2316,0x2114,0x240C,0x240C,0x240C,0x1810,0x1E10,0x2610,0x2710,0x270C,0x260C,0x270C,0x2710,0x2510,
0x2A0C,0x2010,0x1A10,0x2810,0x2810,0x1E10,0x2510,0x2510,0x2510,0x1C14,0x1008,0x1008,0x1008,0x1008,0x1008,0x0F08,
0x0804,0x0A04,0x200C,0x2008,0x1F0C,0x2008,0x200C,0x1E10,0x1610,0x1710,0x1610,0x1610,0x220C,0x1E0C,0x1F0C,0x220C,
0x1E0C,0x1E10,0x1E14,0x1F10,0x1C0C,0x2210,0x1F0C,0x1F0C,0x1F0C,0x1410,0x1810,0x200C,0x210C,0x2110,0x2010,0x2110,
0x210C,0x2110,0x250C,0x1C10,0x1B10,0x2410,0x2210,0x1B10,0x2110,0x2110,0x2110,0x1D10,0x0F08,0x100C,0x1008,0x1008,
0x0A08,0x0608,0x0604,0x0804,0x0908,0x0B08,0x0B08,0x0A04,0x0C08,0x0C08,0x0C08,0x0D08,0x0E08,0x0D08,0x0C08,0x0D08,
0x0E08,0x0E08,0x0E08,0x0C08,0x2D10,0x2D14,0x3118,0x2F1C,0x2C18,0x2A14,0x2A14,0x2A10,0x2910,0x290C,0x2913,0x2B10,
0x2E18,0x2C18,0x3019,0x2B17,0x2714,0x2714,0x2710,0x2710,0x270C,0x2714,0x2310,0x1E0C,0x220C,0x230C,0x230C,0x2210,
0x230C,0x230C,0x250C,0x240C,0x2210,0x1C0C,0x220C,0x220C,0x220C,0x270C,0x280C,0x2810,0x2710,0x2810,0x280C,0x2910,
0x2910,0x2110,0x2810,0x2810,0x2710,0x190C,0x1A0C,0x1A0C,0x190C,0x1A0C,0x1A0C,0x1C0C,0x1C0C,0x180C,0x1710,0x1A0C,
0x1A0C,0x1A0C,0x2010,0x2110,0x2110,0x200C,0x2110,0x2110,0x2410,0x2210,0x1D10,0x2110,0x2110,0x2210,0x0F08,0x0C08,
0x0608,0x0F08,0x0D08,0x1008,0x1008,0x1008,0x3014,0x2018,0x2010,0x0E04,0x0D08,0x2008,0x1008,0x1020,0x1D10,0x1B18,
0x1A10,0x1910,0x1D10,0x1D10,0x1F14,0x1D10,0x170C,0x150C,0x150C,0x1814,0x1614,0x1614,0x2814,0x0814,0x0A14,0x0A14,
0x2010,0x0B18,0x1818,0x1F10,0x1F08,0x1814,0x120D,0x120E,0x120F,0x0608,0x0507,0x0304,0x1D18,0x1E18,0x2018,0x2018,
0x160C,0x170C,0x1020,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F04,0x0F08,0x0F08,0x0F08,0x0F08,
0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F04,0x0F08,0x0404,
0x0408,0x0F08,0x0F04,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0F08,0x0000
};
const uint8_t sprite_palettes[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,
0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x05,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x07,0x07,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
const uint8_t level_data1p[] = {
0x00,0x02,0x00,0x05,0x01,0x00,0x01,0x06,0x02,0x00,0x02,0x01,0x00,0x00,0x01,0x07,
0x02,0x02,0x03,0x01,0x00,0x04,0x00,0x03,0x01,0x01,0x01,0x03,0x02,0x03,0x02,0x04,
0x03,0x06,0x03,0x05,0x00,0x06,0x00,0x08,0x00,0x07,0x01,0x04,0x01,0x05,0x02,0x05,
0x02,0x06,0x02,0x07,0x02,0x08,0x03,0x02,0x03,0x03,0x03,0x04,0x01,0x08,0xFF,0xFF
};
const uint8_t level_data2p[] = {
0x00,0x02,0x00,0x05,0x01,0x00,0x01,0x06,0x02,0x00,0x02,0x01,0x00,0x00,0x01,0x07,
0x02,0x02,0x03,0x01,0x00,0x04,0x00,0x03,0x01,0x01,0x01,0x03,0x02,0x03,0x02,0x04,
0x03,0x06,0x03,0x05,0x00,0x08,0x00,0x07,0x01,0x04,0x01,0x05,0x02,0x05,0x02,0x06,
0x02,0x08,0x03,0x02,0x03,0x03,0x03,0x04,0x01,0x08,0xFF,0xFF
};
const uint8_t level_data3[] = {
0x09,0x09,0x09,0x07,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00
};
const uint8_t level_data4[] = {
0x2D,0x2D,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x30,0x2D,0x2D,0x2D,0x2D,
0x41,0x2D,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x41,0x2D,
0x44,0x46,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x43,0x2D,
0x42,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x37,0x38,0x39,0x2D,0x34,0x35,0x36,0x2D,0x31,
0x32,0x33,0x30,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,
0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x2D,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,
0x01,0x01,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
0x05,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,0x07,0x08,0x08,
0x08,0x09,0x09,0x09,0x0A,0x0A,0x0B,0x0B,0x0C,0x0D,0x0E,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x01,0xFF,0x01,0xFF,
0x01,0xFF,0x01,0xFF,0x02,0xFF,0x02,0xFF,0x03,0xFF,0x04,0xFF,0x05,0xFF,0x07,0xFF,
0x08,0xFF,0x0A,0xFF,0x0C,0xFF,0x0D,0xFF,0x0F,0xFF,0x12,0xFF,0x14,0xFF,0x16,0xFF,
0x19,0xFF,0x1C,0xFF,0x1F,0xFF,0x22,0xFF,0x25,0xFF,0x28,0xFF,0x2C,0xFF,0x2F,0xFF,
0x33,0xFF,0x37,0xFF,0x3B,0xFF,0x3F,0xFF,0x43,0xFF,0x47,0xFF,0x4B,0xFF,0x50,0xFF,
0x55,0xFF,0x59,0xFF,0x5E,0xFF,0x63,0xFF,0x68,0xFF,0x6D,0xFF,0x72,0xFF,0x78,0xFF,
0x7D,0xFF,0x82,0xFF,0x88,0xFF,0x8D,0xFF,0x93,0xFF,0x99,0xFF,0x9F,0xFF,0xA4,0xFF,
0xAA,0xFF,0xB0,0xFF,0xB6,0xFF,0xBC,0xFF,0xC2,0xFF,0xC8,0xFF,0xCF,0xFF,0xD5,0xFF,
0xDB,0xFF,0xE1,0xFF,0xE7,0xFF,0xEE,0xFF,0xF4,0xFF,0xFA,0xFF,0x00,0x00,0x00,0x00,
0x06,0x00,0x0C,0x00,0x12,0x00,0x19,0x00,0x1F,0x00,0x25,0x00,0x2B,0x00,0x31,0x00,
0x38,0x00,0x3E,0x00,0x44,0x00,0x4A,0x00,0x50,0x00,0x56,0x00,0x5C,0x00,0x61,0x00,
0x67,0x00,0x6D,0x00,0x73,0x00,0x78,0x00,0x7E,0x00,0x83,0x00,0x88,0x00,0x8E,0x00,
0x93,0x00,0x98,0x00,0x9D,0x00,0xA2,0x00,0xA7,0x00,0xAB,0x00,0xB0,0x00,0xB5,0x00,
0xB9,0x00,0xBD,0x00,0xC1,0x00,0xC5,0x00,0xC9,0x00,0xCD,0x00,0xD1,0x00,0xD4,0x00,
0xD8,0x00,0xDB,0x00,0xDE,0x00,0xE1,0x00,0xE4,0x00,0xE7,0x00,0xEA,0x00,0xEC,0x00,
0xEE,0x00,0xF1,0x00,0xF3,0x00,0xF4,0x00,0xF6,0x00,0xF8,0x00,0xF9,0x00,0xFB,0x00,
0xFC,0x00,0xFD,0x00,0xFE,0x00,0xFE,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,
0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFE,0x00,0xFE,0x00,0xFD,0x00,0xFC,0x00,0xFB,0x00,
0xF9,0x00,0xF8,0x00,0xF6,0x00,0xF4,0x00,0xF3,0x00,0xF1,0x00,0xEE,0x00,0xEC,0x00,
0xEA,0x00,0xE7,0x00,0xE4,0x00,0xE1,0x00,0xDE,0x00,0xDB,0x00,0xD8,0x00,0xD4,0x00,
0xD1,0x00,0xCD,0x00,0xC9,0x00,0xC5,0x00,0xC1,0x00,0xBD,0x00,0xB9,0x00,0xB5,0x00,
0xB0,0x00,0xAB,0x00,0xA7,0x00,0xA2,0x00,0x9D,0x00,0x98,0x00,0x93,0x00,0x8E,0x00,
0x88,0x00,0x83,0x00,0x7E,0x00,0x78,0x00,0x73,0x00,0x6D,0x00,0x67,0x00,0x61,0x00,
0x5C,0x00,0x56,0x00,0x50,0x00,0x4A,0x00,0x44,0x00,0x3E,0x00,0x38,0x00,0x31,0x00,
0x2B,0x00,0x25,0x00,0x1F,0x00,0x19,0x00,0x12,0x00,0x0C,0x00,0x06,0x00,0x00,0x00,
0xFA,0xFF,0xF4,0xFF,0xEE,0xFF,0xE7,0xFF,0xE1,0xFF,0xDB,0xFF,0xD5,0xFF,0xCF,0xFF,
0xC8,0xFF,0xC2,0xFF,0xBC,0xFF,0xB6,0xFF,0xB0,0xFF,0xAA,0xFF,0xA4,0xFF,0x9F,0xFF,
0x99,0xFF,0x93,0xFF,0x8D,0xFF,0x88,0xFF,0x82,0xFF,0x7D,0xFF,0x78,0xFF,0x72,0xFF,
0x6D,0xFF,0x68,0xFF,0x63,0xFF,0x5E,0xFF,0x59,0xFF,0x55,0xFF,0x50,0xFF,0x4B,0xFF,
0x47,0xFF,0x43,0xFF,0x3F,0xFF,0x3B,0xFF,0x37,0xFF,0x33,0xFF,0x2F,0xFF,0x2C,0xFF,
0x28,0xFF,0x25,0xFF,0x22,0xFF,0x1F,0xFF,0x1C,0xFF,0x19,0xFF,0x16,0xFF,0x14,0xFF,
0x12,0xFF,0x0F,0xFF,0x0D,0xFF,0x0C,0xFF,0x0A,0xFF,0x08,0xFF,0x07,0xFF,0x05,0xFF,
0x04,0xFF,0x03,0xFF,0x02,0xFF,0x02,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,0x01,0xFF,
0x01,0xFF,0x01,0xFF,0x01,0xFF,0x02,0xFF,0x02,0xFF,0x03,0xFF,0x04,0xFF,0x05,0xFF,
0x07,0xFF,0x08,0xFF,0x0A,0xFF,0x0C,0xFF,0x0D,0xFF,0x0F,0xFF,0x12,0xFF,0x14,0xFF,
0x16,0xFF,0x19,0xFF,0x1C,0xFF,0x1F,0xFF,0x22,0xFF,0x25,0xFF,0x28,0xFF,0x2C,0xFF,
0x2F,0xFF,0x33,0xFF,0x37,0xFF,0x3B,0xFF,0x3F,0xFF,0x43,0xFF,0x47,0xFF,0x4B,0xFF,
0x50,0xFF,0x55,0xFF,0x59,0xFF,0x5E,0xFF,0x63,0xFF,0x68,0xFF,0x6D,0xFF,0x72,0xFF,
0x78,0xFF,0x7D,0xFF,0x82,0xFF,0x88,0xFF,0x8D,0xFF,0x93,0xFF,0x99,0xFF,0x9F,0xFF,
0xA4,0xFF,0xAA,0xFF,0xB0,0xFF,0xB6,0xFF,0xBC,0xFF,0xC2,0xFF,0xC8,0xFF,0xCF,0xFF,
0xD5,0xFF,0xDB,0xFF,0xE1,0xFF,0xE7,0xFF,0xEE,0xFF,0xF4,0xFF,0xFA,0xFF,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
0x05,0x00,0x06,0x00,0x07,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
0x0F,0x0E,0x0D,0x0C,0x0B,0x0A,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,
0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,
0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
0x09,0x09,0x08,0x08,0x08,0x07,0x07,0x07,0x06,0x06,0x06,0x05,0x05,0x05,0x04,0x04,
0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,0x09,0x09,
0x04,0x03,0x03,0x03,0x02,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x02,0x03,0x03,0x03,0x04,
0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x0F,0x0F,0x0F,0x0E,
0x0E,0x0E,0x0D,0x0D,0x0D,0x0C,0x0C,0x0C,0x0B,0x0B,0x0B,0x0A,0x0A,0x0A,0x09,0x09,
0x09,0x09,0x0A,0x0A,0x0A,0x0B,0x0B,0x0B,0x0C,0x0C,0x0C,0x0D,0x0D,0x0D,0x0E,0x0E,
0x0E,0x0F,0x0F,0x0F,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
0x00,0x00,0x00,0x00,0x00,0x1D,0x1E,0x00,0x04,0x01,0x01,0x01,0x00,0x00,0x00,0x0B,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x1B,0x05,0x00,0x05,0x00,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x00,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x05,0x1C,0x1A,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x0B,0x0C,0x0D,0x0E,0x0F,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x1F,0x20,0x00,0x00,0x1D,0x1E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1A,
0x19,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,
0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,
0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x00,0x00,
0x00,0x00,0x00,0x00,0x0A,0x0A,0x0A,0x02,0x02,0x00,0x00,0x21,0x22,0x21,0x22,0x0A,
0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x02,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,
0x01,0x01,0x08,0x01,0x01,0x26,0x26,0x26,0x27,0x27,0x27,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x08,0x01,0x02,0x02,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x23,0x23,0x00,0x08,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x23,0x23,0x02,0x08,0x02,0x02,0x00,
0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x23,0x08,
0x08,0x02,0x02,0x00,0x00,0x02,0x00,0x00,0x23,0x23,0x23,0x23,0x00,0x00,0x00,0x00,
0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
0x00,0x00,0x08,0x00,0x02,0x02,0x00,0x23,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x08,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,
0x22,0x21,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x23,0x23,0x23,0x23,0x23,0x23,
0x23,0x23,0x23,0x23,0x02,0x02,0x02,0x02,0x23,0x00,0x00,0x00,0x00,0x02,0x02,0x02,
0x02,0x02,0x02,0x02,0x23,0x02,0x02,0x02,0x02,0x02,0x23,0x02,0x23,0x00,0x00,0x00,
0x02,0x02,0x23,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,
0xAA,0x5D,0x83,0x5E,0x83,0x5E,0xAA,0x5D,0x73,0x5F,0xAA,0x5D,0xAA,0x5D,0x78,0x5F,
0xAA,0x5D,0x83,0x5E,0x83,0x5E,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x0E,0x5F,0x0E,0x5F,0x83,0x5E,0xAA,0x5D,0xAA,0x5D,0xAA,0x5D,0xAA,0x5D,
0xAA,0x5D,0xAA,0x5D,0x0E,0x5F,0xAA,0x5D,0x83,0x5E,0x83,0x5E,0xAA,0x5D,0x73,0x5F,
0xAA,0x5D,0xEC,0x5E,0x78,0x5F,0x3E,0x5D,0x83,0x5E,0x83,0x5E,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x16,0x5F,0x16,0x5F,0xA7,0x5F,0x94,0x5F,
0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x0E,0x5F,0xC8,0x5D,0xC8,0x5D,
0xC9,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC9,0x5D,
0xC9,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,
0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,
0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,
0xC8,0x5D,0x9E,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,
0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0x58,0x5E,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,0xC8,0x5D,
0xC8,0x5D,0xC8,0x5D,0x58,0x5E,0x58,0x5E,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,0x7B,0x5F,
0x7B,0x5F,0x7B,0x5F,0xC8,0x5D,0xC8,0x5D,0x9E,0x5F,0x94,0x5F,0x94,0x5F,0x94,0x5F,
0x94,0x5F,0x94,0x5F,0x94,0x5F,0xC8,0x5D
};
const uint8_t monster_spr_anim_data0[] = {
0xE6,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data1[] = {
0xD6,0x00,0xD7,0x00,0xFE,0xFF,0x00,0x7D,0xD8,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data2[] = {
0xD9,0x00,0xD9,0x00,0xD9,0x00,0xDB,0x00,0xDB,0x00,0xDB,0x00,0xDA,0x00,0xDA,0x00,
0xDA,0x00,0xF7,0xFF,0x00,0x7D,0xDC,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data3[] = {
0xE1,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data4[] = {
0xE1,0x00,0xE1,0x00,0xE2,0x00,0xE3,0x00,0xE3,0x00,0xE2,0x00,0xE1,0x00,0xE1,0x00,
0xF8,0xFF,0xE4,0x00,0xFF,0xFF,0x00,0x7D,0xE5,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data6[] = {
0xEC,0x00,0xEC,0x00,0xED,0x00,0xED,0x00,0xFC,0xFF,0xEE,0x00,0xFF,0xFF,0x00,0x7D,
0xEF,0x00,0xFF,0xFF
};
const uint8_t monster_spr_anim_data8[] = {
0xCE,0x00,0xCE,0x00,0xCE,0x00,0xCF,0x00,0xCF,0x00,0xCF,0x00,0xD0,0x00,0xD0,0x00,
0xD0,0x00,0xD1,0x00,0xD1,0x00,0xD1,0x00,0xF4,0xFF,0xCE,0x00,0xCE,0x00,0xCF,0x00,
0xCF,0x00,0xD0,0x00,0xD0,0x00,0xD1,0x00,0xD1,0x00,0xF8,0xFF,0x00,0x7D,0xD4,0x00,
0xFF,0xFF
};
const uint8_t monster_spr_anim_data9[] = {
0xC6,0x00,0xFF,0xFF
};
const uint8_t common_palette_data[] = {
0x00,0x00,0x00,0x0C,0x14,0x10,0x04,0x0C,0x08,0x3C,0x3C,0x3C,0x1C,0x20,0x28,0x10,
0x14,0x20,0x0C,0x10,0x1C,0x08,0x0C,0x18,0x04,0x08,0x14,0x04,0x04,0x04,0x3C,0x38,
0x30,0x3C,0x30,0x24,0x30,0x24,0x1C,0x24,0x14,0x0C,0x20,0x28,0x24,0x10,0x18,0x14,
0x3F,0x3F,0x3F,0x08,0x08,0x18,0x18,0x10,0x20,0x18,0x18,0x30,0x20,0x20,0x38,0x38,
0x38,0x38,0x3F,0x3E,0x00,0x2F,0x2E,0x00,0x30,0x18,0x10,0x20,0x10,0x00,0x18,0x00,
0x00,0x1C,0x00,0x00,0x27,0x00,0x00,0x33,0x00,0x00,0x3F,0x10,0x10,0x00,0x00,0x00,
0x04,0x28,0x00,0x20,0x1C,0x20,0x1C,0x14,0x1C,0x18,0x0C,0x18,0x10,0x08,0x10,0x0C,
0x04,0x0C,0x08,0x00,0x08,0x04,0x00,0x04,0x24,0x10,0x04,0x1C,0x0C,0x04,0x18,0x08,
0x04,0x14,0x04,0x00,0x0C,0x00,0x00,0x08,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,
0x06,0x07,0x08,0x3C,0x3C,0x3C,0x24,0x2C,0x28,0x2C,0x14,0x10,0x24,0x10,0x0C,0x1C,
0x0C,0x08,0x14,0x08,0x08,0x0C,0x04,0x04,0x04,0x00,0x00,0x0C,0x14,0x10,0x3C,0x38,
0x30,0x3C,0x30,0x24,0x30,0x24,0x1C,0x24,0x14,0x0C,0x20,0x28,0x24,0x10,0x18,0x14,
0x14,0x10,0x0C,0x3C,0x3C,0x3C,0x1C,0x20,0x28,0x10,0x14,0x20,0x0C,0x10,0x1C,0x08,
0x0C,0x18,0x04,0x08,0x14,0x04,0x04,0x10,0x18,0x10,0x18,0x18,0x20,0x1C,0x20,0x18,
0x20,0x0C,0x14,0x10,0x08,0x10,0x0C,0x2C,0x28,0x2C,0x04,0x0C,0x08,0x00,0x08,0x04,
0x14,0x00,0x14,0x10,0x3C,0x3C,0x10,0x34,0x34,0x0C,0x30,0x30,0x0C,0x28,0x28,0x08,
0x24,0x24,0x08,0x1C,0x1C,0x08,0x18,0x18,0x04,0x10,0x10,0x04,0x0C,0x0C,0x00,0x04,
0x04,0x00,0x00,0x00,0x24,0x24,0x24,0x14,0x14,0x14,0x0C,0x0C,0x0C,0x30,0x34,0x34,
0x14,0x14,0x14,0x24,0x1C,0x1C,0x20,0x18,0x18,0x1C,0x14,0x14,0x18,0x10,0x10,0x14,
0x0C,0x0C,0x10,0x08,0x08,0x08,0x04,0x04,0x18,0x18,0x14,0x04,0x04,0x04,0x10,0x10,
0x0C,0x00,0x30,0x00,0x00,0x24,0x00,0x00,0x14,0x00,0x3C,0x3C,0x3C,0x2C,0x1C,0x28,
0x14,0x1C,0x0C,0x3C,0x3C,0x3C,0x28,0x1C,0x1C,0x20,0x14,0x14,0x1C,0x0C,0x0C,0x18,
0x08,0x08,0x10,0x04,0x04,0x0C,0x0C,0x04,0x14,0x14,0x10,0x18,0x18,0x1C,0x18,0x18,
0x14,0x14,0x14,0x18,0x10,0x10,0x14,0x10,0x10,0x08,0x08,0x0C,0x10,0x00,0x08,0x04
};
const uint8_t levels_palette_data[] = {
0x00,0x34,0x38,0x20,0x28,0x10,0x1C,0x28,0x00,0x18,0x20,0x0C,0x10,0x14,0x04,0x08,
0x0C,0x04,0x14,0x18,0x10,0x14,0x14,0x08,0x00,0x08,0x00,0x04,0x0C,0x14,0x08,0x10,
0x18,0x0C,0x14,0x24,0x10,0x1C,0x28,0x14,0x2C,0x34,0x0C,0x20,0x00,0x10,0x24,0x00,
0x00,0x34,0x38,0x30,0x34,0x2C,0x38,0x20,0x10,0x38,0x24,0x20,0x0C,0x20,0x00,0x10,
0x24,0x00,0x14,0x2C,0x00,0x18,0x34,0x00,0x3C,0x30,0x14,0x38,0x10,0x10,0x2D,0x00,
0x2D,0x21,0x00,0x21,0x16,0x00,0x16,0x00,0x10,0x38,0x28,0x3C,0x10,0x28,0x3C,0x10,
0x00,0x34,0x38,0x00,0x28,0x38,0x38,0x2C,0x20,0x34,0x24,0x18,0x2C,0x20,0x18,0x20,
0x18,0x08,0x1C,0x14,0x08,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x14,0x00,0x00,0x18,
0x00,0x00,0x20,0x00,0x1C,0x2C,0x00,0x3C,0x38,0x20,0x28,0x38,0x10,0x20,0x2C,0x00,
0x00,0x34,0x38,0x38,0x3C,0x38,0x00,0x14,0x00,0x00,0x18,0x00,0x00,0x20,0x00,0x08,
0x2C,0x00,0x00,0x00,0x00,0x3C,0x38,0x20,0x18,0x0C,0x08,0x20,0x10,0x08,0x20,0x14,
0x08,0x28,0x18,0x10,0x34,0x20,0x14,0x3C,0x28,0x0C,0x3C,0x2C,0x08,0x00,0x34,0x38,
0x00,0x34,0x38,0x28,0x2C,0x30,0x28,0x00,0x04,0x1C,0x00,0x04,0x00,0x18,0x04,0x00,
0x2C,0x04,0x34,0x38,0x3C,0x10,0x28,0x34,0x28,0x30,0x34,0x34,0x00,0x04,0x20,0x20,
0x24,0x1C,0x1C,0x20,0x14,0x14,0x18,0x10,0x10,0x14,0x0C,0x0C,0x10,0x3C,0x3C,0x3C,
0x00,0x24,0x26,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,
0x00,0x00,0x22,0x07,0x00,0x2B,0x17,0x04,0x35,0x29,0x0A,0x3F,0x3F,0x12,0x00,0x00,
0x06,0x03,0x04,0x11,0x0B,0x0C,0x1D,0x18,0x18,0x28,0x29,0x29,0x33,0x3F,0x3F,0x3F,
0x00,0x24,0x26,0x2C,0x1C,0x14,0x2A,0x18,0x0C,0x26,0x16,0x10,0x20,0x12,0x06,0x1B,
0x10,0x03,0x16,0x0C,0x01,0x12,0x08,0x00,0x04,0x00,0x00,0x3C,0x3C,0x3C,0x1E,0x22,
0x26,0x17,0x1C,0x20,0x11,0x16,0x1B,0x0C,0x10,0x15,0x08,0x0C,0x10,0x04,0x08,0x0C,
0x38,0x2E,0x3F,0x3A,0x3C,0x3E,0x35,0x38,0x3E,0x31,0x35,0x3D,0x2E,0x30,0x3F,0x28,
0x2E,0x3C,0x24,0x2B,0x3C,0x20,0x28,0x3B,0x1C,0x25,0x3B,0x17,0x22,0x3B,0x13,0x1F,
0x3A,0x10,0x1C,0x3A,0x0C,0x19,0x39,0x38,0x32,0x3F,0x32,0x2C,0x3F,0x32,0x2E,0x3F,
0x3F,0x38,0x34,0x3B,0x38,0x31,0x3B,0x37,0x30,0x3B,0x36,0x2F,0x3F,0x35,0x2E,0x3F,
0x33,0x2C,0x3E,0x31,0x2A,0x3D,0x2F,0x29,0x3D,0x2D,0x28,0x3C,0x2C,0x27,0x3C,0x2A,
0x25,0x3B,0x28,0x24,0x3B,0x27,0x23,0x3F,0x37,0x39,0x3F,0x33,0x2E,0x3F,0x35,0x2E,
0x00,0x34,0x38,0x20,0x28,0x10,0x1C,0x28,0x00,0x18,0x20,0x0C,0x10,0x14,0x04,0x08,
0x0C,0x04,0x14,0x18,0x10,0x14,0x14,0x08,0x00,0x08,0x00,0x04,0x0C,0x14,0x08,0x10,
0x18,0x0C,0x14,0x24,0x10,0x1C,0x28,0x14,0x2C,0x34,0x0C,0x20,0x00,0x10,0x24,0x00,
0x1C,0x0C,0x24,0x38,0x3C,0x28,0x1C,0x20,0x00,0x08,0x10,0x00,0x3C,0x3C,0x3C,0x0C,
0x04,0x0C,0x08,0x00,0x08,0x04,0x00,0x04,0x28,0x22,0x1E,0x1C,0x18,0x14,0x14,0x10,
0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x00,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,
0x1C,0x0C,0x24,0x3E,0x36,0x30,0x3E,0x20,0x00,0x32,0x00,0x00,0x3C,0x3C,0x3C,0x0C,
0x04,0x0C,0x08,0x04,0x00,0x00,0x00,0x00,0x28,0x22,0x1E,0x1C,0x18,0x14,0x14,0x10,
0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x00,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,
0x00,0x20,0x00,0x10,0x1C,0x20,0x0C,0x18,0x1C,0x08,0x14,0x18,0x04,0x10,0x14,0x04,
0x0C,0x10,0x00,0x08,0x0C,0x00,0x04,0x08,0x30,0x28,0x0C,0x28,0x1E,0x08,0x22,0x16,
0x04,0x1C,0x0E,0x02,0x14,0x08,0x00,0x0E,0x06,0x00,0x08,0x04,0x00,0x00,0x00,0x00,
0x24,0x34,0x38,0x24,0x10,0x04,0x1C,0x0C,0x04,0x18,0x08,0x04,0x14,0x04,0x00,0x0C,
0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x18,0x14,0x10,0x14,
0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x04,0x00,0x00,0x00,0x00,
0x00,0x24,0x26,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,
0x00,0x00,0x22,0x06,0x00,0x2A,0x16,0x04,0x34,0x28,0x0A,0x3E,0x3E,0x12,0x00,0x00,
0x06,0x02,0x04,0x10,0x0A,0x0C,0x1C,0x18,0x18,0x28,0x28,0x28,0x32,0x3E,0x3E,0x3E,
0x00,0x24,0x26,0x30,0x28,0x0C,0x28,0x1E,0x08,0x22,0x16,0x04,0x1C,0x0E,0x02,0x14,
0x08,0x00,0x0E,0x06,0x00,0x08,0x04,0x00,0x0E,0x18,0x18,0x0C,0x14,0x14,0x0A,0x10,
0x10,0x08,0x0E,0x0C,0x06,0x0A,0x0A,0x04,0x06,0x06,0x02,0x02,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x0A,0x07,0x0A,0x0D,0x0A,0x0E,0x10,0x0E,0x12,0x14,0x12,0x16,0x17,
0x1A,0x1D,0x1B,0x1C,0x1F,0x21,0x1B,0x16,0x1B,0x15,0x11,0x17,0x0F,0x0D,0x12,0x0A,
0x09,0x0D,0x08,0x08,0x3A,0x00,0x34,0x3A,0x00,0x34,0x3A,0x00,0x34,0x3A,0x00,0x34,
0x00,0x00,0x00,0x06,0x0C,0x10,0x09,0x10,0x17,0x0E,0x13,0x1D,0x10,0x14,0x1F,0x16,
0x19,0x25,0x12,0x15,0x21,0x24,0x18,0x20,0x1D,0x13,0x1A,0x16,0x0D,0x15,0x0C,0x0C,
0x11,0x0A,0x0A,0x0E,0x3A,0x00,0x34,0x3A,0x00,0x34,0x3A,0x00,0x34,0x3A,0x00,0x34,
0x00,0x24,0x26,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,
0x00,0x00,0x22,0x07,0x00,0x2B,0x17,0x04,0x35,0x29,0x0A,0x3F,0x3F,0x12,0x00,0x00,
0x06,0x03,0x04,0x11,0x0B,0x0C,0x1D,0x18,0x18,0x28,0x29,0x29,0x33,0x3F,0x3F,0x3F,
0x1C,0x0C,0x24,0x38,0x3C,0x28,0x1C,0x20,0x00,0x08,0x10,0x00,0x3C,0x3C,0x3C,0x0C,
0x04,0x0C,0x08,0x00,0x08,0x04,0x00,0x04,0x28,0x22,0x1E,0x1C,0x18,0x14,0x14,0x10,
0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x00,0x00,0x00,0x00,0x04,0x08,0x00,0x00,0x00,
0x0C,0x2C,0x04,0x28,0x22,0x1E,0x20,0x28,0x1C,0x20,0x24,0x1C,0x18,0x20,0x14,0x14,
0x18,0x0C,0x00,0x18,0x10,0x00,0x00,0x00,0x20,0x1C,0x18,0x1C,0x18,0x14,0x18,0x14,
0x10,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x00,0x00,0x00,0x38,0x38,0x3C,
0x00,0x1C,0x00,0x16,0x14,0x00,0x12,0x11,0x00,0x0F,0x0E,0x00,0x0B,0x0A,0x00,0x07,
0x07,0x00,0x04,0x03,0x00,0x00,0x00,0x00,0x0A,0x08,0x03,0x11,0x0E,0x06,0x19,0x13,
0x09,0x18,0x14,0x0A,0x1E,0x1A,0x10,0x1A,0x1E,0x08,0x24,0x20,0x12,0x2E,0x26,0x1E,
0x24,0x34,0x38,0x20,0x10,0x04,0x18,0x0C,0x04,0x14,0x08,0x04,0x10,0x04,0x00,0x08,
0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x1C,0x20,0x0C,0x18,
0x1C,0x08,0x14,0x18,0x04,0x10,0x14,0x04,0x0C,0x10,0x00,0x08,0x0C,0x00,0x04,0x08,
0x24,0x34,0x38,0x10,0x3C,0x3C,0x10,0x34,0x34,0x0C,0x30,0x30,0x0C,0x28,0x28,0x08,
0x24,0x24,0x08,0x1C,0x1C,0x08,0x18,0x18,0x04,0x10,0x10,0x04,0x0C,0x0C,0x00,0x04,
0x04,0x00,0x00,0x00,0x24,0x24,0x24,0x14,0x14,0x14,0x0C,0x0C,0x0C,0x30,0x34,0x34,
0x3F,0x3F,0x3F,0x3A,0x3D,0x3E,0x36,0x3C,0x3E,0x32,0x3A,0x3E,0x2E,0x39,0x3E,0x2A,
0x37,0x3E,0x26,0x36,0x3F,0x22,0x35,0x3F,0x1E,0x33,0x3F,0x1A,0x32,0x3F,0x16,0x31,
0x3F,0x12,0x2F,0x3F,0x0E,0x2E,0x3F,0x0A,0x2C,0x3F,0x06,0x2B,0x3F,0x02,0x2A,0x3F,
0x00,0x00,0x00,0x0A,0x03,0x03,0x0F,0x05,0x03,0x14,0x07,0x03,0x1A,0x0B,0x03,0x1F,
0x10,0x02,0x23,0x16,0x00,0x0F,0x0B,0x07,0x14,0x11,0x0B,0x1A,0x19,0x10,0x1E,0x1F,
0x15,0x22,0x25,0x1C,0x01,0x3D,0x00,0x01,0x3D,0x00,0x01,0x3D,0x00,0x01,0x3D,0x00,
0x00,0x00,0x00,0x03,0x03,0x05,0x07,0x08,0x0D,0x09,0x0A,0x10,0x0C,0x0D,0x14,0x0F,
0x0F,0x17,0x12,0x12,0x1A,0x0D,0x03,0x00,0x10,0x06,0x00,0x14,0x09,0x00,0x18,0x0D,
0x00,0x1C,0x12,0x00,0x01,0x3D,0x00,0x01,0x3D,0x00,0x01,0x3D,0x00,0x01,0x3D,0x00,
0x00,0x18,0x00,0x20,0x1C,0x18,0x1C,0x18,0x14,0x18,0x14,0x10,0x14,0x10,0x0C,0x10,
0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00,0x18,0x1C,0x18,0x14,0x18,
0x14,0x10,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x04,0x00,
0x00,0x00,0x00,0x1C,0x14,0x14,0x18,0x10,0x10,0x14,0x0C,0x0C,0x10,0x08,0x08,0x0C,
0x04,0x04,0x08,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x1C,0x20,0x1C,0x18,0x1C,
0x18,0x14,0x18,0x14,0x10,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,
0x00,0x00,0x00,0x20,0x1C,0x18,0x1C,0x18,0x14,0x18,0x14,0x10,0x14,0x10,0x0C,0x10,
0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00,0x08,0x08,0x18,0x18,0x18,
0x28,0x1C,0x20,0x30,0x24,0x28,0x3C,0x00,0x08,0x00,0x00,0x28,0x28,0x38,0x38,0x34,
0x00,0x00,0x00,0x3D,0x3F,0x2E,0x3A,0x3F,0x27,0x38,0x3F,0x1F,0x34,0x3F,0x17,0x31,
0x3F,0x10,0x2D,0x3F,0x08,0x28,0x3F,0x00,0x00,0x00,0x00,0x07,0x08,0x17,0x06,0x07,
0x13,0x04,0x05,0x0F,0x03,0x04,0x0B,0x02,0x02,0x08,0x01,0x01,0x04,0x00,0x00,0x00,
0x00,0x18,0x00,0x08,0x08,0x18,0x18,0x10,0x20,0x18,0x18,0x30,0x20,0x20,0x38,0x38,
0x38,0x38,0x28,0x28,0x28,0x23,0x1F,0x1F,0x1E,0x18,0x18,0x1A,0x11,0x11,0x15,0x0C,
0x0C,0x10,0x07,0x07,0x0C,0x04,0x04,0x20,0x2A,0x20,0x38,0x38,0x18,0x00,0x00,0x00,
0x00,0x00,0x00,0x14,0x10,0x0C,0x10,0x0C,0x08,0x0C,0x08,0x04,0x08,0x04,0x00,0x00,
0x00,0x00,0x22,0x07,0x00,0x2B,0x17,0x04,0x35,0x29,0x0A,0x3F,0x3F,0x12,0x00,0x00,
0x06,0x03,0x04,0x11,0x0B,0x0C,0x1D,0x18,0x18,0x28,0x29,0x29,0x33,0x3F,0x3F,0x3F,
0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,
0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,
0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,0x37,0x00,0x00,
0x00,0x00,0x00,0x31,0x24,0x10,0x0B,0x0A,0x12,0x2C,0x1D,0x12,0x25,0x12,0x0E,0x1F,
0x0B,0x0D,0x19,0x08,0x0E,0x12,0x05,0x0D,0x0C,0x03,0x0B,0x37,0x2D,0x1E,0x1A,0x1C,
0x18,0x07,0x14,0x1D,0x0F,0x12,0x12,0x0B,0x0D,0x11,0x0B,0x08,0x10,0x04,0x1F,0x23,
0x00,0x00,0x00,0x14,0x23,0x17,0x12,0x0E,0x0D,0x14,0x20,0x17,0x11,0x1C,0x18,0x0F,
0x19,0x18,0x0D,0x13,0x15,0x0A,0x0D,0x12,0x08,0x08,0x0B,0x1D,0x23,0x17,0x19,0x1E,
0x11,0x19,0x14,0x13,0x08,0x12,0x04,0x08,0x0D,0x0A,0x04,0x09,0x04,0x22,0x1B,0x1A
};
const uint8_t tile_lut_data0[] = {
0x01,0xFA,0x06,0x00
};
const uint8_t tile_lut_data1[] = {
0x05,0xFA,0x06,0x00,0x87,0x03,0x01,0x8A,0x03,0x02,0xD5,0x03,0x01,0xD8,0x03,0x02
};
const uint8_t tile_lut_data2[] = {
0x06,0xFA,0x06,0x00,0x80,0x03,0x01,0x83,0x03,0x02,0x87,0x03,0x02,0x8A,0x03,0x01,
0x8D,0x03,0x02
};
const uint8_t tile_lut_data3[] = {
0x01,0xFA,0x06,0x00
};
const uint16_t tile_funcs0[] = {
0x5DAA,0x5E83,0x5E83,0x5DAA,0x5F73,0x5DAA,0x5DAA,0x5F78,0x5DAA,0x5E83,0x5E83,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5F0E,0x5F0E,0x5E83,0x5DAA,0x5DAA,0x5DAA,0x5DAA,0x5DAA,0x5DAA,0x5F0E
};
const uint16_t tile_funcs1[] = {
0x5DAA,0x5E83,0x5E83,0x5DAA,0x5F73,0x5DAA,0x5EEC,0x5F78,0x5D3E,0x5E83,0x5E83,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5F16,0x5F16,0x5FA7,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5F0E
};
const uint16_t tile_funcs2[] = {
0x5DC8,0x5DC8,0x5DC9,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC9,0x5DC9,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,
0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,
0x5DC8,0x5DC8,0x5DC8,0x5F9E,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5DC8
};
const uint16_t tile_funcs3[] = {
0x5DC8,0x5DC8,0x5E58,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5DC8,0x5E58,0x5E58,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,0x5F7B,
0x5F7B,0x5DC8,0x5DC8,0x5F9E,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5F94,0x5DC8
};
const uint8_t level_data_tiles_lut[] = {
0x00,0x00,0x00,0x00,0x00,0x1D,0x1E,0x00,0x04,0x01,0x01,0x01,0x00,0x00,0x00,0x0B,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x1B,0x05,0x00,0x05,0x00,0x01,0x01,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x00,0x07,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x05,0x1C,0x1A,0x05,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
0x00,0x0B,0x0C,0x0D,0x0E,0x0F,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x0B,0x0C,0x0D,0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x00,0x00,
0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x2A,0x2A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x1F,0x20,0x00,0x00,0x1D,0x1E,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x1A,
0x19,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,
0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,
0x00,0x02,0x02,0x00,0x00,0x02,0x02,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x00,0x00,0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x00,0x00,
0x00,0x00,0x00,0x00,0x0A,0x0A,0x0A,0x02,0x02,0x00,0x00,0x21,0x22,0x21,0x22,0x0A,
0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x02,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,
0x01,0x01,0x08,0x01,0x01,0x26,0x26,0x26,0x27,0x27,0x27,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
0x09,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x01,0x08,0x01,0x02,0x02,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x23,0x23,0x00,0x08,0x00,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x23,0x23,0x02,0x08,0x02,0x02,0x00,
0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x23,0x23,0x08,
0x08,0x02,0x02,0x00,0x00,0x02,0x00,0x00,0x23,0x23,0x23,0x23,0x00,0x00,0x00,0x00,
0x24,0x24,0x24,0x25,0x25,0x25,0x02,0x26,0x26,0x26,0x27,0x27,0x27,0x28,0x28,0x28,
0x00,0x00,0x08,0x00,0x02,0x02,0x00,0x23,0x00,0x00,0x00,0x21,0x22,0x21,0x22,0x08,
0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06,
0x00,0x01,0x01,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,
0x22,0x21,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x02,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x02,0x02,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x23,0x23,0x23,0x23,0x23,0x23,
0x23,0x23,0x23,0x23,0x02,0x02,0x02,0x02,0x23,0x00,0x00,0x00,0x00,0x02,0x02,0x02,
0x02,0x02,0x02,0x02,0x23,0x02,0x02,0x02,0x02,0x02,0x23,0x02,0x23,0x00,0x00,0x00,
0x02,0x02,0x23,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x06,0x06,0x06,0x06
};
const uint8_t player_anim_dy[] = {
0xFF,0xFE,0xFC,0xF9,0xF2,0xEA,0xDA,0x00
};
const uint8_t player_anim_lut[] = {
0x00,0x02,0x04,0x03,0x02,0x00,0x03,0x00,0x05,0x05,0x00,0x00,0x05,0x00,0x00,0x00,
0x06,0x06,0x07,0x07,0x06,0x06,0x07,0x00,0x06,0x06,0x00,0x00,0x06,0x00,0x00,0x00,
0x0D,0x0F,0x11,0x11,0x0F,0x0D,0x11,0x0D,0x12,0x12,0x0D,0x0D,0x12,0x0D,0x0D,0x0D,
0x13,0x13,0x14,0x14,0x13,0x13,0x14,0x0D,0x13,0x13,0x0D,0x0D,0x13,0x0D,0x0D,0x0D,
0x15,0x17,0x19,0x19,0x17,0x15,0x19,0x15,0x1A,0x1A,0x15,0x15,0x1A,0x15,0x15,0x15,
0x1B,0x1B,0x1C,0x1C,0x1B,0x1B,0x1C,0x15,0x1B,0x1B,0x15,0x15,0x1B,0x15,0x15,0x15,
0x15,0x17,0x19,0x19,0x17,0x15,0x19,0x15,0x1A,0x1A,0x15,0x15,0x1A,0x15,0x15,0x15,
0x1B,0x1B,0x1C,0x1C,0x1B,0x1B,0x1C,0x15,0x1B,0x1B,0x15,0x15,0x1B,0x15,0x15,0x15,
0x09,0x0B,0x0A,0x0A,0x0C,0x09,0x0A,0x0A,0x08,0x05,0x09,0x09,0x05,0x08,0x09,0x09,
0x06,0x06,0x06,0x06,0x06,0x09,0x06,0x09,0x06,0x06,0x09,0x09,0x06,0x09,0x09,0x09,
0x1E,0x20,0x1F,0x1F,0x21,0x1E,0x1F,0x1F,0x1D,0x12,0x1E,0x1E,0x12,0x1D,0x1E,0x1E,
0x13,0x13,0x13,0x13,0x13,0x1E,0x13,0x1E,0x13,0x13,0x1E,0x1E,0x13,0x1E,0x1E,0x1E
};
static const uint8_t tab6278[] = {
0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,
0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,
0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0x14,0x00,
0x14,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0x16,0x00,0x16,0x00,
0x16,0x00,0x16,0x00,0x16,0x00,0xF1,0xFF
};
static const uint8_t tab62c0[] = {
0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,
0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x11,0x00,0x11,0x00,
0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x40,0x12,0x40,0x12,0x40,0x12,0x40,
0x12,0x40,0x12,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,
0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
0x12,0x00,0x12,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x11,0x40,0x11,0x40,
0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x12,0x40,
0x12,0x40,0x12,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,
0x12,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x11,0x40,0x11,0x40,
0x11,0x40,0x11,0x40,0x11,0x40,0x11,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x11,0x40,
0x11,0x40,0x11,0x40,0x12,0x40,0x12,0x40,0x12,0x40,0x11,0x00,0x11,0x00,0x11,0x00,
0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
0x12,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,
0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x11,0x00,0x11,0x00,0x11,0x00,
0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,
0x12,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x12,0x00,
0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x14,0x20,0xFF,0xFF
};
static const uint8_t tab63ee[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x03,0x00,0x03,0x00,0x03,0x00,0x03,0x00,
0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,
0xE8,0xFF
};
static const uint8_t tab6420[] = {
0x06,0x00,0x06,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
0x09,0x00,0x09,0x00,0x09,0x00,0xF7,0xFF
};
static const uint8_t tab6438[] = {
0x06,0x00,0xFF,0xFF
};
static const uint8_t tab643c[] = {
0x0A,0x00,0xFF,0xFF
};
static const uint8_t tab6440[] = {
0x10,0x00,0x10,0x20,0x10,0x00,0xFD,0xFF
};
static const uint8_t tab6448[] = {
0x17,0x00,0x17,0x20,0x17,0x00,0xFD,0xFF
};
static const uint8_t tab6266[] = {
0x0D,0x00,0x0D,0x00,0x0E,0x00,0x0E,0x00,0x0D,0x40,0x0D,0x40,0x0E,0x40,0x0E,0x40,
0xF8,0xFF
};
static const uint8_t tab6262[] = {
0x0D,0x00,0xFF,0xFF
};
static const uint8_t tab6450[] = {
0x26,0x00,0x26,0x00,0x26,0x00,0x26,0x00,0x26,0x00,0x26,0x00,0x26,0x00,0x27,0x00,
0x27,0x00,0x27,0x00,0x27,0x00,0x27,0x00,0x27,0x00,0x27,0x00,0x28,0x00,0x28,0x00,
0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x28,0x00,0x27,0x00,0x27,0x00,0x27,0x00,
0x27,0x00,0x27,0x00,0x27,0x00,0x27,0x00,0xE4,0xFF
};
static const uint8_t tab648a[] = {
0x19,0x00,0x19,0x00,0x19,0x00,0x19,0x00,0x1A,0x00,0x1A,0x00,0x1A,0x00,0x1A,0x00,
0x1B,0x00,0x1B,0x00,0x1B,0x00,0x1B,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,0x1C,0x00,
0x1D,0x00,0x1D,0x00,0x1D,0x00,0x1D,0x00,0x1E,0x00,0x1E,0x00,0x1E,0x00,0x1E,0x00,
0xE8,0xFF
};
static const uint8_t tab64bc[] = {
0x21,0x00,0xFF,0xFF
};
static const uint8_t tab64c0[] = {
0x23,0x00,0xFF,0xFF
};
static const uint8_t tab64c4[] = {
0x29,0x00,0x29,0x20,0xFF,0xFF
};
static const uint8_t tab64ca[] = {
0x22,0x00,0x22,0x20,0xFF,0xFF
};
static const uint8_t tab64e6[] = {
0x96,0x00,0x96,0x00,0x96,0x00,0x96,0x00,0x96,0x00,0x96,0x00,0x96,0x00,0x97,0x00,
0x97,0x00,0x97,0x00,0x97,0x00,0x97,0x00,0x97,0x00,0x97,0x00,0x98,0x00,0x98,0x00,
0x98,0x00,0x98,0x00,0x98,0x00,0x98,0x00,0x98,0x00,0x97,0x00,0x97,0x00,0x97,0x00,
0x97,0x00,0x97,0x00,0x97,0x00,0x97,0x00,0xE4,0xFF
};
static const uint8_t tab6520[] = {
0x8C,0x00,0x8C,0x00,0x8C,0x00,0x8C,0x00,0x8D,0x00,0x8D,0x00,0x8D,0x00,0x8D,0x00,
0x8E,0x00,0x8E,0x00,0x8E,0x00,0x8E,0x00,0x8F,0x00,0x8F,0x00,0x8F,0x00,0x8F,0x00,
0x90,0x00,0x90,0x00,0x90,0x00,0x90,0x00,0x91,0x00,0x91,0x00,0x91,0x00,0x91,0x00,
0xE8,0xFF
};
static const uint8_t tab6552[] = {
0x95,0x00,0xFF,0xFF
};
static const uint8_t tab6556[] = {
0x92,0x00,0xFF,0xFF
};
static const uint8_t tab655a[] = {
0x18,0x20,0xFF,0xFF
};
static const uint8_t tab655e[] = {
0x17,0x20,0xFF,0xFF
};
static const uint8_t tab64d4[] = {
0x1F,0x00,0x1F,0x00,0x20,0x00,0x20,0x00,0x1F,0x40,0x1F,0x40,0x20,0x40,0x20,0x40,
0xF8,0xFF
};
static const uint8_t tab64d0[] = {
0x1F,0x00,0xFF,0xFF
};
static const uint8_t tab625e[] = {
0x8A,0x00,0xFF,0xFF
};
static const uint8_t tab6562[] = {
0x25,0x00,0xFF,0xFF
};
const uint8_t *player_anim_table[] = {
tab6278,tab62c0,tab63ee,tab6420,
tab6438,tab643c,tab6440,tab6448,
tab6266,tab6262,tab6266,tab6266,
tab6266,tab6450, 0,tab648a,
0,tab64bc,tab64c0,tab64c4,
tab64ca,tab64e6, 0,tab6520,
0,tab6552,tab6556,tab655a,
tab655e,tab64d4,tab64d0,tab64d4,
tab64d4,tab64d4,tab625e,tab6562,
};

129
ja/unpack.c Normal file
View File

@ -0,0 +1,129 @@
/* uncompress data packed with DIET by T.Matsumoto */
#include "unpack.h"
#include "util.h"
struct unpack_eat_t {
FILE *fp;
uint8_t len;
uint16_t bits;
uint8_t *dst;
};
static struct unpack_eat_t g_unpack;
static uint16_t fread_le16(FILE *fp) {
const uint16_t val = fgetc(fp);
return val | (fgetc(fp) << 8);
}
static int next_bit(struct unpack_eat_t *u) {
const int bit = (u->bits & (1 << (16 - u->len))) != 0;
--u->len;
if (u->len == 0) {
u->bits = fread_le16(u->fp);
u->len = 16;
}
return bit;
}
static int zero_bits(struct unpack_eat_t *u, int count) {
int i = 0;
for (; i < count; ++i) {
if (next_bit(u)) {
break;
}
}
return i;
}
static uint8_t get_bits(struct unpack_eat_t *u, int count) {
assert(count < 8);
uint8_t val = 0;
for (int i = 0; i < count; ++i) {
val = (val << 1) | next_bit(u);
}
return val;
}
static void copy_reference(struct unpack_eat_t *u, int count, int offset_hi, int offset_lo) {
const int16_t offset = offset_hi * 256 + offset_lo;
for (int i = 0; i < count; ++i) {
const uint8_t value = u->dst[offset];
*u->dst++ = value;
}
}
static int unpack_eat(struct unpack_eat_t *u, uint8_t *output_buffer, int output_buffer_size) {
uint8_t buffer[17];
const int header_size = fread(buffer, 1, sizeof(buffer), u->fp);
if (header_size != 17 || READ_LE_UINT16(buffer + 4) != 0x899D || READ_LE_UINT16(buffer + 6) != 0x6C64) {
print_error("Unexpected signature for .eat file");
return 0;
}
const uint16_t crc = READ_LE_UINT16(buffer + 12);
const int output_size = (buffer[14] << 14) + READ_LE_UINT16(buffer + 15);
print_debug(DBG_UNPACK, "uncompressed size %d crc 0x%04x", output_size, crc);
if (output_size > output_buffer_size) {
print_error("Invalid output buffer size %d, need %d", output_buffer_size, output_size);
return 0;
}
u->dst = output_buffer;
u->len = 16;
u->bits = fread_le16(u->fp);
while (1) {
while (next_bit(u)) {
*u->dst++ = fgetc(u->fp);
}
const int b = next_bit(u);
const int offset_lo = fgetc(u->fp);
if (b) {
int offset_hi = 0xFE | next_bit(u);
if (!next_bit(u)) {
int i = 1;
for (; i < 4 && !next_bit(u); ++i) {
offset_hi = (offset_hi << 1) | next_bit(u);
}
offset_hi -= (1 << i);
}
const int n = zero_bits(u, 4);
if (n != 4) {
copy_reference(u, n + 3, offset_hi, offset_lo);
} else if (next_bit(u)) {
copy_reference(u, next_bit(u) + 7, offset_hi, offset_lo);
} else if (!next_bit(u)) {
copy_reference(u, get_bits(u, 3) + 9, offset_hi, offset_lo);
} else {
copy_reference(u, fgetc(u->fp) + 17, offset_hi, offset_lo);
}
} else {
if (next_bit(u)) {
const int offset_hi = (0xF8 | get_bits(u, 3)) - 1;
copy_reference(u, 2, offset_hi, offset_lo);
} else if (offset_lo == 0xFF) {
break;
} else {
copy_reference(u, 2, 0xFF, offset_lo);
}
}
}
assert((u->dst - output_buffer) == output_size);
return output_size;
}
int unpack(const char *filename, uint8_t *dst, int size) {
int uncompressed_size = 0;
FILE *fp = fopen(filename, "rb");
if (fp) {
memset(&g_unpack, 0, sizeof(struct unpack_eat_t));
g_unpack.fp = fp;
uncompressed_size = unpack_eat(&g_unpack, dst, size);
fclose(fp);
} else {
print_error("Unable to open '%s'", filename);
}
return uncompressed_size;
}

9
ja/unpack.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef UNPACK_H__
#define UNPACK_H__
#include "intern.h"
extern int unpack(const char *filename, uint8_t *dst, int size);
#endif /* UNPACK_H__ */

46
main.c
View File

@ -1,10 +1,6 @@
#include <getopt.h>
#include <sys/stat.h>
#include "fileio.h"
#include "game.h"
#include "resource.h"
#include "sys.h"
#include "util.h"
@ -23,12 +19,33 @@ static const char *USAGE =
" --cheats=MASK Cheats mask\n"
" --startpos=XxY Start at position (X,Y)\n"
" --fullscreen Enable fullscreen\n"
" --scale Graphics scaling factor (default 2)\n"
" --filter Graphics scaling filter\n"
" --scale=N Graphics scaling factor (default 2)\n"
" --filter=NAME Graphics scaling filter (default 'nearest')\n"
" --screensize=WxH Graphics screen size (default 320x200)\n"
" --cga Enable CGA colors\n"
;
static struct game_t *detect_game(const char *data_path) {
#if 0
extern struct game_t bb_game;
extern struct game_t ja_game;
static struct game_t *games[] = {
&bb_game,
&ja_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
}
int main(int argc, char *argv[]) {
g_options.start_xpos16 = -1;
g_options.start_ypos16 = -1;
@ -97,7 +114,7 @@ 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;
g_options.screen_h = ((g_options.screen_h + 15) & ~15) + 40; // PANEL_H
}
break;
case 10:
@ -108,16 +125,15 @@ int main(int argc, char *argv[]) {
return -1;
}
}
fio_init(data_path);
res_init(GAME_SCREEN_W * GAME_SCREEN_H);
struct game_t *game = detect_game(data_path);
if (!game) {
fprintf(stdout, "No data files found\n");
} else {
g_sys.init();
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, "Blues Brothers", scale_factor, scale_filter, fullscreen);
sound_init();
game_main();
sound_fini();
g_sys.set_screen_size(GAME_SCREEN_W, GAME_SCREEN_H, game->name, scale_factor, scale_filter, fullscreen);
game->run(data_path);
g_sys.fini();
res_fini();
fio_fini();
}
if (data_path != DEFAULT_DATA_PATH) {
free((char *)data_path);
}

4
sys.h
View File

@ -16,6 +16,7 @@ struct input_t {
bool quit;
bool escape;
bool space;
bool digit1, digit2, digit3;
};
typedef void (*sys_audio_cb)(void *, uint8_t *data, int len);
@ -35,9 +36,10 @@ struct sys_t {
int (*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);
void (*set_screen_palette)(const uint8_t *colors, int offset, int count, int depth);
void (*set_palette_amiga)(const uint16_t *colors, int offset);
void (*set_copper_bars)(const uint16_t *data);
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);

View File

@ -33,7 +33,7 @@ static SDL_Window *_window;
static SDL_Renderer *_renderer;
static SDL_Texture *_texture;
static SDL_PixelFormat *_fmt;
static uint32_t _screen_palette[48];
static uint32_t _screen_palette[256];
static uint32_t *_screen_buffer;
static struct input_t *_input = &g_sys.input;
static int _copper_color;
@ -158,22 +158,41 @@ static void sdl2_set_copper_bars(const uint16_t *data) {
}
}
static void sdl2_set_screen_palette(const uint8_t *colors, int count) {
static void sdl2_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) {
_screen_palette[i] = SDL_MapRGB(_fmt, colors[0], colors[1], colors[2]);
int r = colors[0];
int g = colors[1];
int b = colors[2];
if (depth != 8) {
r = (r << shift) | (r >> (depth - shift));
g = (g << shift) | (g >> (depth - shift));
b = (b << shift) | (b >> (depth - shift));
}
_screen_palette[offset + i] = SDL_MapRGB(_fmt, r, g, b);
colors += 3;
}
}
static void sdl2_set_palette_color(int i, const uint8_t *colors) {
int r = colors[0];
r = (r << 2) | (r >> 4);
int g = colors[1];
g = (g << 2) | (g >> 4);
int b = colors[2];
b = (b << 2) | (b >> 4);
_screen_palette[i] = SDL_MapRGB(_fmt, r, g, b);
}
static void fade_palette_helper(int in) {
SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
SDL_Rect r;
r.x = r.y = 0;
SDL_GetRendererOutputSize(_renderer, &r.w, &r.h);
for (int i = 1; i <= FADE_STEPS; ++i) {
int alpha = 256 * i / FADE_STEPS;
for (int i = 0; i <= FADE_STEPS; ++i) {
int alpha = 255 * i / FADE_STEPS;
if (in) {
alpha = 256 - alpha;
alpha = 255 - alpha;
}
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, alpha);
SDL_RenderClear(_renderer);
@ -313,6 +332,15 @@ static void handle_keyevent(int keysym, bool keydown) {
case SDLK_ESCAPE:
_input->escape = keydown;
break;
case SDLK_1:
_input->digit1 = keydown;
break;
case SDLK_2:
_input->digit2 = keydown;
break;
case SDLK_3:
_input->digit3 = keydown;
break;
}
}
@ -490,6 +518,7 @@ struct sys_t g_sys = {
.set_screen_palette = sdl2_set_screen_palette,
.set_palette_amiga = sdl2_set_palette_amiga,
.set_copper_bars = sdl2_set_copper_bars,
.set_palette_color = sdl2_set_palette_color,
.fade_in_palette = sdl2_fade_in_palette,
.fade_out_palette = sdl2_fade_out_palette,
.update_screen = sdl2_update_screen,